📄 menu.c
字号:
{
txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
DT_SINGLELINE|DT_CALCRECT);
ItemInfo->Rect.right += rc.right - rc.left;
itemheight = max( max( itemheight, txtheight),
GetSystemMetrics( SM_CYMENU) - 1);
ItemInfo->Rect.right += 2 * MenuCharSize.cx;
}
else
{
if ((p = strchrW( ItemInfo->dwTypeData, '\t' )) != NULL)
{
RECT tmprc = rc;
LONG tmpheight;
int n = (int)( p - ItemInfo->dwTypeData);
/* Item contains a tab (only meaningful in popup menus) */
/* get text size before the tab */
txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, n, &rc,
DT_SINGLELINE|DT_CALCRECT);
txtwidth = rc.right - rc.left;
p += 1; /* advance past the Tab */
/* get text size after the tab */
tmpheight = DrawTextW( Dc, p, -1, &tmprc, DT_SINGLELINE|DT_CALCRECT);
ItemInfo->XTab += txtwidth;
txtheight = max( txtheight, tmpheight);
txtwidth += MenuCharSize.cx + /* space for the tab */
tmprc.right - tmprc.left; /* space for the short cut */
}
else
{
txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
DT_SINGLELINE|DT_CALCRECT);
txtwidth = rc.right - rc.left;
ItemInfo->XTab += txtwidth;
}
ItemInfo->Rect.right += 2 + txtwidth;
itemheight = max( itemheight, max( txtheight + 2, MenuCharSize.cy + 4));
}
if (hfontOld) SelectObject (Dc, hfontOld);
}
else if( MenuBar)
{
itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
}
ItemInfo->Rect.bottom += itemheight;
DPRINT("(%ld,%ld)-(%ld,%ld)\n", ItemInfo->Rect.left, ItemInfo->Rect.top, ItemInfo->Rect.right, ItemInfo->Rect.bottom);
}
/***********************************************************************
* MenuPopupMenuCalcSize
*
* Calculate the size of a popup menu.
*/
static void FASTCALL
MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
{
ROSMENUITEMINFO ItemInfo;
HDC Dc;
int Start, i;
int OrgX, OrgY, MaxX, MaxTab, MaxTabWidth;
MenuInfo->Width = MenuInfo->Height = 0;
if (0 == MenuInfo->MenuItemCount)
{
MenuSetRosMenuInfo(MenuInfo);
return;
}
Dc = GetDC(NULL);
SelectObject(Dc, hMenuFont);
Start = 0;
MaxX = 2 + 1;
MenuInfo->maxBmpSize.cx = 0;
MenuInfo->maxBmpSize.cy = 0;
MenuInitRosMenuItemInfo(&ItemInfo);
while (Start < MenuInfo->MenuItemCount)
{
OrgX = MaxX;
OrgY = 2;
MaxTab = MaxTabWidth = 0;
/* Parse items until column break or end of menu */
for (i = Start; i < MenuInfo->MenuItemCount; i++)
{
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
MenuSetRosMenuInfo(MenuInfo);
return;
}
if (i != Start &&
0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
{
break;
}
MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, FALSE);
if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
MenuSetRosMenuInfo(MenuInfo);
return;
}
// Not sure here,, The patch from wine removes this.
// if (0 != (ItemInfo.fType & MF_MENUBARBREAK))
// {
// OrgX++;
// }
MaxX = max(MaxX, ItemInfo.Rect.right);
OrgY = ItemInfo.Rect.bottom;
if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
{
MaxTab = max(MaxTab, ItemInfo.XTab);
MaxTabWidth = max(MaxTabWidth, ItemInfo.Rect.right - ItemInfo.XTab);
}
}
/* Finish the column (set all items to the largest width found) */
MaxX = max(MaxX, MaxTab + MaxTabWidth);
while (Start < i)
{
if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
{
ItemInfo.Rect.right = MaxX;
if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
{
ItemInfo.XTab = MaxTab;
}
MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
}
Start++;
}
MenuInfo->Height = max(MenuInfo->Height, OrgY);
}
MenuInfo->Width = MaxX;
/* space for 3d border */
MenuInfo->Height += 2;
MenuInfo->Width += 2;
ReleaseDC(NULL, Dc);
MenuCleanupRosMenuItemInfo(&ItemInfo);
MenuSetRosMenuInfo(MenuInfo);
}
/***********************************************************************
* MenuMenuBarCalcSize
*
* FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
* height is off by 1 pixel which causes lengthy window relocations when
* active document window is maximized/restored.
*
* Calculate the size of the menu bar.
*/
static void FASTCALL
MenuMenuBarCalcSize(HDC Dc, LPRECT Rect, PROSMENUINFO MenuInfo, HWND WndOwner)
{
ROSMENUITEMINFO ItemInfo;
int Start, i, OrgX, OrgY, MaxY, HelpPos;
if (NULL == Rect || NULL == MenuInfo)
{
return;
}
if (0 == MenuInfo->MenuItemCount)
{
return;
}
DPRINT("left=%ld top=%ld right=%ld bottom=%ld\n",
Rect->left, Rect->top, Rect->right, Rect->bottom);
MenuInfo->Width = Rect->right - Rect->left;
MenuInfo->Height = 0;
MaxY = Rect->top + 1;
Start = 0;
HelpPos = -1;
MenuInfo->maxBmpSize.cx = 0;
MenuInfo->maxBmpSize.cy = 0;
MenuInitRosMenuItemInfo(&ItemInfo);
while (Start < MenuInfo->MenuItemCount)
{
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
OrgX = Rect->left;
OrgY = MaxY;
/* Parse items until line break or end of menu */
for (i = Start; i < MenuInfo->MenuItemCount; i++)
{
if (-1 == HelpPos && 0 != (ItemInfo.fType & MF_RIGHTJUSTIFY))
{
HelpPos = i;
}
if (i != Start &&
0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
{
break;
}
DPRINT("calling MENU_CalcItemSize org=(%d, %d)\n", OrgX, OrgY);
MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, TRUE);
if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
if (ItemInfo.Rect.right > Rect->right)
{
if (i != Start)
{
break;
}
else
{
ItemInfo.Rect.right = Rect->right;
}
}
MaxY = max(MaxY, ItemInfo.Rect.bottom );
OrgX = ItemInfo.Rect.right;
if (i + 1 < MenuInfo->MenuItemCount)
{
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
}
}
/* FIXME: Is this really needed? */ /*NO! it is not needed, why make the
HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */
#if 0
/* Finish the line (set all items to the largest height found) */
while (Start < i)
{
if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
{
ItemInfo.Rect.bottom = MaxY;
MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
}
Start++;
}
#else
Start = i; /* This works! */
#endif
}
Rect->bottom = MaxY;
MenuInfo->Height = Rect->bottom - Rect->top;
MenuSetRosMenuInfo(MenuInfo);
if (-1 != HelpPos)
{
/* Flush right all items between the MF_RIGHTJUSTIFY and */
/* the last item (if several lines, only move the last line) */
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
OrgY = ItemInfo.Rect.top;
OrgX = Rect->right;
for (i = MenuInfo->MenuItemCount - 1; HelpPos <= i; i--)
{
if (i < HelpPos)
{
break; /* done */
}
if (ItemInfo.Rect.top != OrgY)
{
break; /* Other line */
}
if (OrgX <= ItemInfo.Rect.right)
{
break; /* Too far right already */
}
ItemInfo.Rect.left += OrgX - ItemInfo.Rect.right;
ItemInfo.Rect.right = OrgX;
OrgX = ItemInfo.Rect.left;
MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
if (HelpPos + 1 <= i &&
! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
{
MenuCleanupRosMenuItemInfo(&ItemInfo);
return;
}
}
}
MenuCleanupRosMenuItemInfo(&ItemInfo);
}
/***********************************************************************
* DrawMenuBarTemp (USER32.@)
*
* UNDOCUMENTED !!
*
* called by W98SE desk.cpl Control Panel Applet
*
* Not 100% sure about the param names, but close.
*
* @implemented
*/
DWORD WINAPI
DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
{
ROSMENUINFO MenuInfo;
ROSMENUITEMINFO ItemInfo;
UINT i;
HFONT FontOld = NULL;
BOOL flat_menu = FALSE;
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
if (NULL == Menu)
{
Menu = GetMenu(Wnd);
}
if (NULL == Font)
{
Font = hMenuFont;
}
if (NULL == Rect || ! MenuGetRosMenuInfo(&MenuInfo, Menu))
{
return GetSystemMetrics(SM_CYMENU);
}
DPRINT("(%x, %x, %p, %x, %x)\n", Wnd, DC, Rect, Menu, Font);
FontOld = SelectObject(DC, Font);
if (0 == MenuInfo.Height)
{
MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
}
Rect->bottom = Rect->top + MenuInfo.Height;
FillRect(DC, Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
SelectObject(DC, GetSysColorPen(COLOR_3DFACE));
MoveToEx(DC, Rect->left, Rect->bottom, NULL);
LineTo(DC, Rect->right, Rect->bottom);
if (0 == MenuInfo.MenuItemCount)
{
SelectObject(DC, FontOld);
return GetSystemMetrics(SM_CYMENU);
}
MenuInitRosMenuItemInfo(&ItemInfo);
for (i = 0; i < MenuInfo.MenuItemCount; i++)
{
if (MenuGetRosMenuItemInfo(MenuInfo.Self, i, &ItemInfo))
{
MenuDrawMenuItem(Wnd, &MenuInfo, Wnd, DC, &ItemInfo,
MenuInfo.Height, TRUE, ODA_DRAWENTIRE);
}
}
MenuCleanupRosMenuItemInfo(&ItemInfo);
SelectObject(DC, FontOld);
return MenuInfo.Height;
}
/***********************************************************************
* MenuDrawMenuBar
*
* Paint a menu bar. Returns the height of the menu bar.
* called from [windows/nonclient.c]
*/
UINT MenuDrawMenuBar(HDC DC, LPRECT Rect, HWND Wnd, BOOL SuppressDraw)
{
ROSMENUINFO MenuInfo;
HFONT FontOld = NULL;
HMENU Menu = GetMenu(Wnd);
if (NULL == Rect || ! MenuGetRosMenuInfo(&MenuInfo, Menu))
{
return GetSystemMetrics(SM_CYMENU);
}
if (SuppressDraw)
{
FontOld = SelectObject(DC, hMenuFont);
MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
Rect->bottom = Rect->top + MenuInfo.Height;
if (NULL != FontOld)
{
SelectObject(DC, FontOld);
}
return MenuInfo.Height;
}
else
{
return DrawMenuBarTemp(Wnd, DC, Rect, Menu, NULL);
}
}
/***********************************************************************
* MenuInitTracking
*/
static BOOL FASTCALL
MenuInitTracking(HWND Wnd, HMENU Menu, BOOL Popup, UINT Flags)
{
DPRINT("Wnd=%p Menu=%p\n", Wnd, Menu);
HideCaret(0);
/* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
if (0 == (Flags & TPM_NONOTIFY))
{
SendMessageW(Wnd, WM_ENTERMENULOOP, Popup, 0);
}
SendMessageW(Wnd, WM_SETCURSOR, (WPARAM) Wnd, HTCAPTION);
if (0 == (Flags & TPM_NONOTIFY))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -