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

📄 menu.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
}

/***********************************************************************
 *           MenuDrawPopupMenu
 *
 * Paint a popup menu.
 */
static void FASTCALL
MenuDrawPopupMenu(HWND Wnd, HDC Dc, HMENU Menu)
{
  HBRUSH PrevBrush = NULL;
  HPEN PrevPen;
  RECT Rect;
  ROSMENUINFO MenuInfo;
  ROSMENUITEMINFO ItemInfo;
  UINT u;

  DPRINT("wnd=%x dc=%x menu=%x\n", Wnd, Dc, Menu);

  GetClientRect(Wnd, &Rect);

  if (NULL != (PrevBrush = SelectObject(Dc, GetSysColorBrush(COLOR_MENU)))
      && NULL != SelectObject(Dc, hMenuFont))
    {
      Rectangle(Dc, Rect.left, Rect.top, Rect.right, Rect.bottom);

      PrevPen = SelectObject(Dc, GetStockObject(NULL_PEN));
      if (NULL != PrevPen)
        {
          BOOL flat_menu = FALSE;

          SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
          if (flat_menu)
             FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_BTNSHADOW));
          else
             DrawEdge(Dc, &Rect, EDGE_RAISED, BF_RECT);

          /* draw menu items */

          if (MenuGetRosMenuInfo(&MenuInfo, Menu) && 0 != MenuInfo.MenuItemCount)
            {
              MenuInitRosMenuItemInfo(&ItemInfo);

              for (u = 0; u < MenuInfo.MenuItemCount; u++)
                {
                  if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
                    {
                      MenuDrawMenuItem(Wnd, &MenuInfo, MenuInfo.WndOwner, Dc, &ItemInfo,
				       MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
                    }
                }

	      MenuCleanupRosMenuItemInfo(&ItemInfo);
	    }
	}
      else
        {
          SelectObject(Dc, PrevBrush);
	}
    }
}

static LRESULT WINAPI
PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
  DPRINT("hwnd=%x msg=0x%04x wp=0x%04x lp=0x%08lx\n", Wnd, Message, wParam, lParam);

  switch(Message)
    {
    case WM_CREATE:
      {
        CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
        SetWindowLongPtrW(Wnd, 0, (LONG) cs->lpCreateParams);
        return 0;
      }

    case WM_MOUSEACTIVATE:  /* We don't want to be activated */
      return MA_NOACTIVATE;

    case WM_PAINT:
      {
        PAINTSTRUCT ps;
        BeginPaint(Wnd, &ps);
        MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrW(Wnd, 0));
        EndPaint(Wnd, &ps);
        return 0;
      }

    case WM_ERASEBKGND:
      return 1;

    case WM_DESTROY:
      /* zero out global pointer in case resident popup window was destroyed. */
      if (Wnd == TopPopup)
        {
          TopPopup = NULL;
        }
      break;

    case WM_SHOWWINDOW:
      if (0 != wParam)
        {
          if (0 == GetWindowLongPtrW(Wnd, 0))
            {
              OutputDebugStringA("no menu to display\n");
            }
        }
      else
        {
          SetWindowLongPtrW(Wnd, 0, 0);
        }
      break;

    case MM_SETMENUHANDLE:
      SetWindowLongPtrW(Wnd, 0, wParam);
      break;

    case MM_GETMENUHANDLE:
      return GetWindowLongPtrW(Wnd, 0);

    default:
      return DefWindowProcW(Wnd, Message, wParam, lParam);
    }

  return 0;
}

/**********************************************************************
 *         MENUEX_ParseResource
 *
 * Parse an extended menu resource and add items to the menu.
 * Return a pointer to the end of the resource.
 *
 * FIXME - should we be passing an LPCSTR to a predominantly UNICODE function?
 */
static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
{
  WORD resinfo;

  do
    {
      MENUITEMINFOW mii;

      mii.cbSize = sizeof(mii);
      mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
      mii.fType = GET_DWORD(res);
      res += sizeof(DWORD);
      mii.fState = GET_DWORD(res);
      res += sizeof(DWORD);
      mii.wID = GET_DWORD(res);
      res += sizeof(DWORD);
      resinfo = GET_WORD(res);
      res += sizeof(WORD);
      /* Align the text on a word boundary.  */
      res += (~((int)res - 1)) & 1;
      mii.dwTypeData = (LPWSTR) res;
      res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
      /* Align the following fields on a dword boundary.  */
      res += (~((int)res - 1)) & 3;

      if (resinfo & 1) /* Pop-up? */
	{
	  /* DWORD helpid = GET_DWORD(res); FIXME: use this.  */
	  res += sizeof(DWORD);
	  mii.hSubMenu = CreatePopupMenu();
	  if (!mii.hSubMenu)
	      return NULL;
	  if (!(res = MENUEX_ParseResource(res, mii.hSubMenu)))
	  {
	      DestroyMenu(mii.hSubMenu);
	      return NULL;
	  }
	  mii.fMask |= MIIM_SUBMENU;
	  mii.fType |= MF_POPUP;
	}
      else if(!*mii.dwTypeData && !(mii.fType & MF_SEPARATOR))
	{
	  mii.fType |= MF_SEPARATOR;
	}
    InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
  }
  while (!(resinfo & MF_END));
  return res;
}


/**********************************************************************
 *         MENU_ParseResource
 *
 * Parse a standard menu resource and add items to the menu.
 * Return a pointer to the end of the resource.
 *
 * NOTE: flags is equivalent to the mtOption field
 */
static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
{
  WORD flags, id = 0;
  HMENU hSubMenu;
  LPCSTR str;
  BOOL end = FALSE;

  do
  {
    flags = GET_WORD(res);

    /* remove MF_END flag before passing it to AppendMenu()! */
    end = (flags & MF_END);
    if(end) flags ^= MF_END;

    res += sizeof(WORD);
    if(!(flags & MF_POPUP))
    {
      id = GET_WORD(res);
      res += sizeof(WORD);
    }
    str = res;
    if(!unicode)
      res += strlen(str) + 1;
    else
      res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
    if (flags & MF_POPUP)
    {
      hSubMenu = CreatePopupMenu();
      if(!hSubMenu) return NULL;
      if(!(res = MENU_ParseResource(res, hSubMenu, unicode)))
        return NULL;
      if(!unicode)
        AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
      else
        AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
    }
    else  /* Not a popup */
    {
      if(!unicode)
        AppendMenuA(hMenu, flags, id, *str ? str : NULL);
      else
        AppendMenuW(hMenu, flags, id,
                    *(LPCWSTR)str ? (LPCWSTR)str : NULL);
    }
  } while(!end);

  return res;
}


NTSTATUS STDCALL
User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
{
  LRESULT Result;
  Result = (LRESULT)LoadMenuW(User32Instance, L"SYSMENU");
  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
}


BOOL
MenuInit(VOID)
{
  NONCLIENTMETRICSW ncm;

  /* get the menu font */
  if(!hMenuFont || !hMenuFontBold)
  {
    ncm.cbSize = sizeof(ncm);
    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
    {
      DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
      return FALSE;
    }

    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
    if(hMenuFont == NULL)
    {
      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
      return FALSE;
    }

    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
    if(hMenuFontBold == NULL)
    {
      DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
      DeleteObject(hMenuFont);
      hMenuFont = NULL;
      return FALSE;
    }
  }

  return TRUE;
}


VOID
MenuCleanup(VOID)
{
  if (hMenuFont)
  {
    DeleteObject(hMenuFont);
    hMenuFont = NULL;
  }

  if (hMenuFontBold)
  {
    DeleteObject(hMenuFontBold);
    hMenuFontBold = NULL;
  }
}



/***********************************************************************
 *           MenuCalcItemSize
 *
 * Calculate the size of the menu item and store it in ItemInfo->rect.
 */
static void FASTCALL
MenuCalcItemSize(HDC Dc, PROSMENUITEMINFO ItemInfo, PROSMENUINFO MenuInfo, HWND WndOwner,
                 INT OrgX, INT OrgY, BOOL MenuBar)
{
  PWCHAR p;
  INT itemheight = 0;
  UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);

  DPRINT("dc=%x owner=%x (%d,%d)\n", Dc, WndOwner, OrgX, OrgY);

  MenuCharSize.cx = GdiGetCharDimensions( Dc, NULL, &MenuCharSize.cy );

  SetRect(&ItemInfo->Rect, OrgX, OrgY, OrgX, OrgY);

  if (0 != (ItemInfo->fType & MF_OWNERDRAW))
    {
      /*
       ** Experimentation under Windows reveals that an owner-drawn
       ** menu is expected to return the size of the content part of
       ** the menu item, not including the checkmark nor the submenu
       ** arrow.  Windows adds those values itself and returns the
       ** enlarged rectangle on subsequent WM_DRAWITEM messages.
       */
      MEASUREITEMSTRUCT mis;
      mis.CtlType    = ODT_MENU;
      mis.CtlID      = 0;
      mis.itemID     = ItemInfo->wID;
      mis.itemData   = (DWORD)ItemInfo->dwItemData;
      mis.itemHeight = HIWORD( GetDialogBaseUnits());
      mis.itemWidth  = 0;
      SendMessageW(WndOwner, WM_MEASUREITEM, 0, (LPARAM) &mis);
   /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average
    * width of a menufont character to the width of an owner-drawn menu.
    */
      ItemInfo->Rect.right += mis.itemWidth + 2 *  MenuCharSize.cx;

      if (MenuBar)
        {
          /* under at least win95 you seem to be given a standard
             height for the menu and the height value is ignored */
            ItemInfo->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
        }
      else
        {
          ItemInfo->Rect.bottom += mis.itemHeight;
        }

      DPRINT("id=%04x size=%dx%d\n", ItemInfo->wID, mis.itemWidth, mis.itemHeight);
      return;
    }

  if (0 != (ItemInfo->fType & MF_SEPARATOR))
    {
      ItemInfo->Rect.bottom += SEPARATOR_HEIGHT;
      if( !MenuBar)
            ItemInfo->Rect.right += ArrowBitmapWidth +  MenuCharSize.cx;
      return;
    }
  
  ItemInfo->XTab = 0;
  
  if (ItemInfo->hbmpItem)
  {
      SIZE Size;

      if (!MenuBar)  /* hbmpItem */
      {
         MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
      /* Keep the size of the bitmap in callback mode to be able
       * to draw it correctly */
         ItemInfo->Rect.right = ItemInfo->Rect.left + Size.cx;
         if (MenuInfo->maxBmpSize.cx < abs(Size.cx) +  MENU_ITEM_HBMP_SPACE ||
             MenuInfo->maxBmpSize.cy < abs(Size.cy))
         {
             MenuInfo->maxBmpSize.cx = abs(Size.cx) + MENU_ITEM_HBMP_SPACE;
             MenuInfo->maxBmpSize.cy = abs(Size.cy);
         }
         MenuSetRosMenuInfo(MenuInfo);
         ItemInfo->Rect.right += Size.cx + 2;
         itemheight = Size.cy + 2;

         if( !(MenuInfo->dwStyle & MNS_NOCHECK))
           ItemInfo->Rect.right += 2 * CheckBitmapWidth;
         ItemInfo->Rect.right += 4 + MenuCharSize.cx;
         ItemInfo->XTab = ItemInfo->Rect.right;
         ItemInfo->Rect.right += ArrowBitmapWidth;
      }
      else /* hbmpItem & MenuBar */
      {
        MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
        ItemInfo->Rect.right  += Size.cx;
          if( ItemInfo->Text) ItemInfo->Rect.right  += 2;
          itemheight = Size.cy;

      /* Special case: Minimize button doesn't have a space behind it. */
        if (ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
            ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
        ItemInfo->Rect.right -= 1;
      }
  }
  else if (!MenuBar)
  {
      if( !(MenuInfo->dwStyle & MNS_NOCHECK))
           ItemInfo->Rect.right += CheckBitmapWidth;
      ItemInfo->Rect.right += 4 + MenuCharSize.cx;
      ItemInfo->XTab = ItemInfo->Rect.right;
      ItemInfo->Rect.right += ArrowBitmapWidth;
  }

  /* it must be a text item - unless it's the system menu */
  if (0 == (ItemInfo->fType & MF_SYSMENU) && ItemInfo->Text)
  {
     HFONT hfontOld = NULL;
     RECT rc = ItemInfo->Rect;
     LONG txtheight, txtwidth;

     if ( ItemInfo->fState & MFS_DEFAULT )
     {
        hfontOld = SelectObject( Dc, hMenuFontBold );
     }
     if (MenuBar) 

⌨️ 快捷键说明

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