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

📄 menu.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: menu.c 23579 2006-08-14 14:44:40Z jimtabor $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS user32.dll
 * FILE:            user32/windows/menu.c
 * PURPOSE:         Menus
 *
 * PROGRAMMERS:     Casper S. Hornstrup
 *                  James Tabor
 */

/* INCLUDES ******************************************************************/

#include <user32.h>

#include <wine/debug.h>

/* internal popup menu window messages */
#define MM_SETMENUHANDLE (WM_USER + 0)
#define MM_GETMENUHANDLE (WM_USER + 1)

/* Internal MenuTrackMenu() flags */
#define TPM_INTERNAL		0xF0000000
#define TPM_ENTERIDLEEX	 	0x80000000		/* set owner window for WM_ENTERIDLE */
#define TPM_BUTTONDOWN		0x40000000		/* menu was clicked before tracking */
#define TPM_POPUPMENU           0x20000000              /* menu is a popup menu */

/* TYPES *********************************************************************/

#define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)

#define MENU_ITEM_TYPE(flags) ((flags) & MENU_TYPE_MASK)
#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))

#define IS_SYSTEM_MENU(MenuInfo)  \
	(0 == ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))

#define IS_SYSTEM_POPUP(MenuInfo) \
	(0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))

#define IS_MAGIC_ITEM(Bmp)   ((int) Bmp <12)
#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))

#define MENU_ITEM_HBMP_SPACE (5)
#define MENU_BAR_ITEMS_SPACE (12)
#define SEPARATOR_HEIGHT (5)
#define MENU_TAB_SPACE (8)

#define ITEM_PREV		-1
#define ITEM_NEXT		 1

#define MAKEINTATOMA(atom)  ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
#define MAKEINTATOMW(atom)  ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
#define POPUPMENU_CLASS_ATOMA   MAKEINTATOMA(32768)  /* PopupMenu */
#define POPUPMENU_CLASS_ATOMW   MAKEINTATOMW(32768)  /* PopupMenu */

/* internal flags for menu tracking */

#define TF_ENDMENU              0x0001
#define TF_SUSPENDPOPUP         0x0002
#define TF_SKIPREMOVE		0x0004

typedef struct
{
  UINT  TrackFlags;
  HMENU CurrentMenu; /* current submenu (can be equal to hTopMenu)*/
  HMENU TopMenu;     /* initial menu */
  HWND  OwnerWnd;    /* where notifications are sent */
  POINT Pt;
} MTRACKER;

static LRESULT WINAPI PopupMenuWndProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

/*********************************************************************
 * PopupMenu class descriptor
 */
const struct builtin_class_descr POPUPMENU_builtin_class =
{
    POPUPMENU_CLASS_ATOMW,                     /* name */
    CS_SAVEBITS | CS_DBLCLKS,                  /* style  */
    (WNDPROC) PopupMenuWndProcW,               /* FIXME - procW */
    (WNDPROC) NULL,                            /* FIXME - procA */
    sizeof(MENUINFO *),                        /* extra */
    (LPCWSTR) IDC_ARROW,                       /* cursor */
    (HBRUSH)(COLOR_MENU + 1)                   /* brush */
};


/* INTERNAL FUNCTIONS ********************************************************/

/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
 * Of course I didnt copy the ASM code because we want this to be portable
 * and it needs to go away.
 */

#ifndef GET_WORD
#define GET_WORD(ptr)  (*(WORD *)(ptr))
#endif
#ifndef GET_DWORD
#define GET_DWORD(ptr) (*(DWORD *)(ptr))
#endif

HFONT hMenuFont = NULL;
HFONT hMenuFontBold = NULL;

/* Flag set by EndMenu() to force an exit from menu tracking */
static BOOL fEndMenu = FALSE;

/* Use global popup window because there's no way 2 menus can
 * be tracked at the same time.  */
static HWND TopPopup;

/* Dimension of the menu bitmaps */
static WORD ArrowBitmapWidth = 0, ArrowBitmapHeight = 0;

static HBITMAP StdMnArrow = NULL;
static HBITMAP BmpSysMenu = NULL;

static SIZE MenuCharSize;

/***********************************************************************
 *           MenuGetRosMenuInfo
 *
 * Get full information about menu
 */
static BOOL FASTCALL
MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
{
  MenuInfo->cbSize = sizeof(ROSMENUINFO);
  MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;

  return NtUserMenuInfo(Menu, MenuInfo, FALSE);
}

/***********************************************************************
 *           MenuSetRosMenuInfo
 *
 * Set full information about menu      
 */
static BOOL FASTCALL
MenuSetRosMenuInfo(PROSMENUINFO MenuInfo)
{
  MenuInfo->cbSize = sizeof(ROSMENUINFO);
  MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;

  return NtUserMenuInfo(MenuInfo->Self, MenuInfo, TRUE);
}

/***********************************************************************
 *           MenuInitRosMenuItemInfo
 *
 * Initialize a buffer for use with MenuGet/SetRosMenuItemInfo
 */
static VOID FASTCALL
MenuInitRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
{
  ZeroMemory(ItemInfo, sizeof(ROSMENUITEMINFO));
  ItemInfo->cbSize = sizeof(ROSMENUITEMINFO);
}

/***********************************************************************
 *           MenuGetRosMenuItemInfo
 *
 * Get full information about a menu item
 */
static BOOL FASTCALL
MenuGetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
{
  UINT Save_Mask = ItemInfo->fMask; /* Save the org mask bits. */
  
  if (ItemInfo->dwTypeData != NULL)
    {
      HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
    }
  

  ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
             | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
  ItemInfo->dwTypeData = NULL;

  if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE))
    {
      ItemInfo->fType = 0;
      return FALSE;
    }

  if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING)
    {
      ItemInfo->cch++;
      ItemInfo->dwTypeData = HeapAlloc(GetProcessHeap(), 0,
                                       ItemInfo->cch * sizeof(WCHAR));
      if (NULL == ItemInfo->dwTypeData)
        {
          return FALSE;
        }

      if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE))
        {
          ItemInfo->fType = 0;
          return FALSE;
        }
    }
  ItemInfo->fMask =  Save_Mask;
  return TRUE;
}

/***********************************************************************
 *           MenuSetRosMenuItemInfo
 *
 * Set selected information about a menu item, need to set the mask bits.
 */
static BOOL FASTCALL
MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
{
  BOOL Ret;

  if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING &&
      ItemInfo->dwTypeData != NULL)
  {
    ItemInfo->cch = strlenW(ItemInfo->dwTypeData);
  }
  Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE);

  return Ret;
}

/***********************************************************************
 *           MenuCleanupRosMenuItemInfo
 *
 * Cleanup after use of MenuGet/SetRosMenuItemInfo
 */
static VOID FASTCALL
MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
{
  if (ItemInfo->dwTypeData != NULL)
    {
      HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData);
    }
}

/***********************************************************************
 *           MenuGetAllRosMenuItemInfo
 *
 * Get full information about all menu items
 */
static INT FASTCALL
MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo)
{
  DWORD BufSize;

  BufSize = NtUserBuildMenuItemList(Menu, (VOID *) 1, 0, 0);
  if (BufSize <= 0)
    {
      return -1;
    }
  *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize);
  if (NULL == *ItemInfo)
    {
      return -1;
    }

  return NtUserBuildMenuItemList(Menu, *ItemInfo, BufSize, 0);
}

/***********************************************************************
 *           MenuCleanupAllRosMenuItemInfo
 *
 * Cleanup after use of MenuGetAllRosMenuItemInfo
 */
static VOID FASTCALL
MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
{
  HeapFree(GetProcessHeap(), 0, ItemInfo);
}


/***********************************************************************
 *           MenuLoadBitmaps
 *
 * Load the arrow bitmap. We can't do this from MenuInit since user32
 * can also be used (and thus initialized) from text-mode.
 */
static void FASTCALL
MenuLoadBitmaps(VOID)
{
  /* Load menu bitmaps */
  if (NULL == StdMnArrow)
    {
      StdMnArrow = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW));

      if (NULL != StdMnArrow)
        {
          BITMAP bm;
          GetObjectW(StdMnArrow, sizeof(BITMAP), &bm);
          ArrowBitmapWidth = bm.bmWidth;
          ArrowBitmapHeight = bm.bmHeight;
        }
    }

  /* Load system buttons bitmaps */
  if (NULL == BmpSysMenu)
    {
      BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
    }
}

/***********************************************************************
 *           MenuGetBitmapItemSize
 *
 * Get the size of a bitmap item.
 */
static void FASTCALL
MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
{
  BITMAP Bm;
  HBITMAP Bmp = lpitem->hbmpItem;

  Size->cx = Size->cy = 0;

  /* check if there is a magic menu item associated with this item */
  if (0 != Bmp && IS_MAGIC_ITEM((INT)(Bmp)))
    {
      switch((INT_PTR) Bmp)
        {
            case (INT_PTR)HBMMENU_CALLBACK:
            {
                MEASUREITEMSTRUCT measItem;
                measItem.CtlType = ODT_MENU;
                measItem.CtlID = 0;
                measItem.itemID = lpitem->wID;
                measItem.itemWidth = lpitem->Rect.right - lpitem->Rect.left;
                measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top;
                measItem.itemData = lpitem->dwItemData;
                SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
                Size->cx = measItem.itemWidth;
                Size->cy = measItem.itemHeight;
                return;
            }
            break;

          case (INT_PTR) HBMMENU_SYSTEM:
            if (0 != lpitem->dwItemData)
              {
                Bmp = (HBITMAP) lpitem->dwItemData;
                break;
              }
            /* fall through */
          case (INT_PTR) HBMMENU_MBAR_RESTORE:
          case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
          case (INT_PTR) HBMMENU_MBAR_CLOSE:
          case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
          case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
            /* FIXME: Why we need to subtract these magic values? */
            /* to make them smaller than the menu bar? */
            Size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
            Size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
            return;
          case (INT_PTR) HBMMENU_POPUP_CLOSE:
          case (INT_PTR) HBMMENU_POPUP_RESTORE:
          case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
          case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
          default:
            DPRINT("Magic menu bitmap not implemented\n");
            return;
        }
    }

  if (GetObjectW(Bmp, sizeof(BITMAP), &Bm))
    {
      Size->cx = Bm.bmWidth;
      Size->cy = Bm.bmHeight;
    }
}

/***********************************************************************
 *           MenuDrawBitmapItem
 *
 * Draw a bitmap item.
 */
static void FASTCALL
MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
                    HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar)
{
  BITMAP Bm;
  DWORD Rop;
  HDC DcMem;
  HBITMAP Bmp;
  int w = Rect->right - Rect->left;
  int h = Rect->bottom - Rect->top;
  int BmpXoffset = 0;
  int Left, Top;
  HBITMAP hbmpToDraw = (HBITMAP) Item->hbmpItem;
  Bmp = hbmpToDraw;

  /* Check if there is a magic menu item associated with this item */
  if (IS_MAGIC_ITEM(hbmpToDraw))
    {
      UINT Flags = 0;
      RECT r;

      r = *Rect;
      switch ((INT_PTR)hbmpToDraw)
        {
          case (INT_PTR) HBMMENU_SYSTEM:
            if (NULL != Item->dwTypeData)
              {
                Bmp = (HBITMAP)Item->dwTypeData;
                if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
                  {
                    return;
                  }
              }
            else
              {
                if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
                Bmp = BmpSysMenu;
                if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
                  {
                    return;
                  }
                /* only use right half of the bitmap */
                BmpXoffset = Bm.bmWidth / 2;
                Bm.bmWidth -= BmpXoffset;
              }
            goto got_bitmap;
          case (INT_PTR) HBMMENU_MBAR_RESTORE:
            Flags = DFCS_CAPTIONRESTORE;
            break;
          case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
            r.right += 1;
            Flags = DFCS_CAPTIONMIN;
            break;
          case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
            r.right += 1;

⌨️ 快捷键说明

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