📄 menu.c
字号:
Flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
break;
case (INT_PTR) HBMMENU_MBAR_CLOSE:
Flags = DFCS_CAPTIONCLOSE;
break;
case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
Flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
break;
case (INT_PTR) HBMMENU_CALLBACK:
{
DRAWITEMSTRUCT drawItem;
POINT origorg;
drawItem.CtlType = ODT_MENU;
drawItem.CtlID = 0;
drawItem.itemID = Item->wID;
drawItem.itemAction = odaction;
drawItem.itemState = (Item->fState & MF_CHECKED)?ODS_CHECKED:0;
drawItem.itemState |= (Item->fState & MF_DEFAULT)?ODS_DEFAULT:0;
drawItem.itemState |= (Item->fState & MF_DISABLED)?ODS_DISABLED:0;
drawItem.itemState |= (Item->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
drawItem.itemState |= (Item->fState & MF_HILITE)?ODS_SELECTED:0;
drawItem.hwndItem = (HWND)hmenu;
drawItem.hDC = Dc;
drawItem.rcItem = *Rect;
drawItem.itemData = Item->dwItemData;
/* some applications make this assumption on the DC's origin */
SetViewportOrgEx( Dc, Item->Rect.left, Item->Rect.top, &origorg);
OffsetRect( &drawItem.rcItem, - Item->Rect.left, - Item->Rect.top);
SendMessageW( WndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
SetViewportOrgEx( Dc, origorg.x, origorg.y, NULL);
return;
}
break;
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;
}
InflateRect(&r, -1, -1);
if (0 != (Item->fState & MF_HILITE))
{
Flags |= DFCS_PUSHED;
}
DrawFrameControl(Dc, &r, DFC_CAPTION, Flags);
return;
}
if (NULL == Bmp || ! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
{
return;
}
got_bitmap:
DcMem = CreateCompatibleDC(Dc);
SelectObject(DcMem, Bmp);
/* handle fontsize > bitmap_height */
Top = (Bm.bmHeight < h) ? Rect->top + (h - Bm.bmHeight) / 2 : Rect->top;
Left = Rect->left;
Rop= ((Item->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmpToDraw)) ? NOTSRCCOPY : SRCCOPY;
if ((Item->fState & MF_HILITE) && Item->hbmpItem)
{
SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
}
BitBlt(Dc, Left, Top, w, h, DcMem, BmpXoffset, 0, Rop);
DeleteDC(DcMem);
}
/***********************************************************************
* MenuDrawMenuItem
*
* Draw a single menu item.
*/
static void FASTCALL
MenuDrawMenuItem(HWND Wnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
PROSMENUITEMINFO Item, UINT Height, BOOL MenuBar, UINT Action)
{
RECT Rect;
PWCHAR Text;
BOOL flat_menu = FALSE;
int bkgnd;
if (0 != (Item->fType & MF_SYSMENU))
{
if (! IsIconic(Wnd))
{
UserGetInsideRectNC(Wnd, &Rect);
UserDrawSysMenuButton(Wnd, Dc, &Rect,
Item->fState & (MF_HILITE | MF_MOUSESELECT));
}
return;
}
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
bkgnd = (MenuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
/* Setup colors */
if (0 != (Item->fState & MF_HILITE))
{
if (MenuBar && !flat_menu)
{
SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
SetBkColor(Dc, GetSysColor(COLOR_MENU));
}
else
{
if (0 != (Item->fState & MF_GRAYED))
{
SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
}
else
{
SetTextColor(Dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
}
}
else
{
if (0 != (Item->fState & MF_GRAYED))
{
SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
}
else
{
SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
}
SetBkColor(Dc, GetSysColor(bkgnd));
}
Rect = Item->Rect;
if (Item->fType & MF_OWNERDRAW)
{
/*
** Experimentation under Windows reveals that an owner-drawn
** menu is given the rectangle which includes the space it requested
** in its response to WM_MEASUREITEM _plus_ width for a checkmark
** and a popup-menu arrow. This is the value of lpitem->rect.
** Windows will leave all drawing to the application except for
** the popup-menu arrow. Windows always draws that itself, after
** the menu owner has finished drawing.
*/
DRAWITEMSTRUCT dis;
dis.CtlType = ODT_MENU;
dis.CtlID = 0;
dis.itemID = Item->wID;
dis.itemData = (DWORD)Item->dwItemData;
dis.itemState = 0;
if (0 != (Item->fState & MF_CHECKED))
{
dis.itemState |= ODS_CHECKED;
}
if (0 != (Item->fState & MF_GRAYED))
{
dis.itemState |= ODS_GRAYED | ODS_DISABLED;
}
if (0 != (Item->fState & MF_HILITE))
{
dis.itemState |= ODS_SELECTED;
}
dis.itemAction = Action; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
dis.hwndItem = (HWND) MenuInfo->Self;
dis.hDC = Dc;
dis.rcItem = Rect;
DPRINT("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
"hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", Wnd,
dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
dis.rcItem.bottom);
SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
/* Draw the popup-menu arrow */
if (0 != (Item->fType & MF_POPUP))
{
HDC DcMem = CreateCompatibleDC(Dc);
HBITMAP OrigBitmap;
OrigBitmap = SelectObject(DcMem, StdMnArrow);
BitBlt(Dc, Rect.right - ArrowBitmapWidth - 1,
((Rect.top + Rect.bottom) - ArrowBitmapHeight) / 2,
ArrowBitmapWidth, ArrowBitmapHeight,
DcMem, 0, 0, SRCCOPY);
SelectObject(DcMem, OrigBitmap);
DeleteDC(DcMem);
}
return;
}
DPRINT("rect={%ld,%ld,%ld,%ld}\n", Item->Rect.left, Item->Rect.top,
Item->Rect.right, Item->Rect.bottom);
if (MenuBar && 0 != (Item->fType & MF_SEPARATOR))
{
return;
}
if (Item->fState & MF_HILITE)
{
if (flat_menu)
{
InflateRect (&Rect, -1, -1);
FillRect(Dc, &Rect, GetSysColorBrush(COLOR_MENUHILIGHT));
InflateRect (&Rect, 1, 1);
FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
}
else
{
if (MenuBar)
{
DrawEdge(Dc, &Rect, BDR_SUNKENOUTER, BF_RECT);
}
else
{
FillRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
}
}
}
else
{
FillRect(Dc, &Rect, GetSysColorBrush(bkgnd));
}
SetBkMode(Dc, TRANSPARENT);
/* vertical separator */
if (! MenuBar && 0 != (Item->fType & MF_MENUBARBREAK))
{
HPEN oldPen;
RECT rc = Rect;
rc.left -= 3;
rc.top = 3;
rc.bottom = Height - 3;
if (flat_menu)
{
oldPen = SelectObject( Dc, GetSysColorPen(COLOR_BTNSHADOW) );
MoveToEx( Dc, rc.left, rc.top, NULL );
LineTo( Dc, rc.left, rc.bottom );
SelectObject( Dc, oldPen );
}
else
DrawEdge(Dc, &rc, EDGE_ETCHED, BF_LEFT);
}
/* horizontal separator */
if (0 != (Item->fType & MF_SEPARATOR))
{
HPEN oldPen;
RECT rc = Rect;
rc.left++;
rc.right--;
rc.top += SEPARATOR_HEIGHT / 2;
if (flat_menu)
{
oldPen = SelectObject( Dc, GetSysColorPen(COLOR_BTNSHADOW) );
MoveToEx( Dc, rc.left, rc.top, NULL );
LineTo( Dc, rc.right, rc.top );
SelectObject( Dc, oldPen );
}
else
DrawEdge(Dc, &rc, EDGE_ETCHED, BF_TOP);
return;
}
#if 0
/* helper lines for debugging */
/* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
FrameRect(Dc, &Rect, GetStockObject(BLACK_BRUSH));
SelectObject(Dc, GetSysColorPen(COLOR_WINDOWFRAME));
MoveToEx(Dc, Rect.left, (Rect.top + Rect.bottom) / 2, NULL);
LineTo(Dc, Rect.right, (Rect.top + Rect.bottom) / 2);
#endif
if (! MenuBar)
{
INT y = Rect.top + Rect.bottom;
RECT Rc = Rect;
UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
UINT CheckBitmapHeight = GetSystemMetrics(SM_CYMENUCHECK);
int checked = FALSE;
/* Draw the check mark
*
* FIXME:
* Custom checkmark bitmaps are monochrome but not always 1bpp.
*/
if( !(MenuInfo->dwStyle & MNS_NOCHECK))
{
HBITMAP bm = 0 != (Item->fState & MF_CHECKED) ? Item->hbmpChecked : Item->hbmpUnchecked;
if (NULL != bm) /* we have a custom bitmap */
{
HDC DcMem = CreateCompatibleDC(Dc);
SelectObject(DcMem, bm);
BitBlt(Dc, Rc.left, (y - CheckBitmapHeight) / 2,
CheckBitmapWidth, CheckBitmapHeight,
DcMem, 0, 0, SRCCOPY);
DeleteDC(DcMem);
checked = TRUE;
}
else if (0 != (Item->fState & MF_CHECKED)) /* standard bitmaps */
{
RECT r;
HBITMAP bm = CreateBitmap(CheckBitmapWidth, CheckBitmapHeight, 1, 1, NULL);
HDC DcMem = CreateCompatibleDC(Dc);
SelectObject(DcMem, bm);
SetRect( &r, 0, 0, CheckBitmapWidth, CheckBitmapHeight);
DrawFrameControl(DcMem, &r, DFC_MENU,
0 != (Item->fType & MFT_RADIOCHECK) ?
DFCS_MENUBULLET : DFCS_MENUCHECK);
BitBlt(Dc, Rc.left, (y - r.bottom) / 2, r.right, r.bottom,
DcMem, 0, 0, SRCCOPY );
DeleteDC(DcMem);
DeleteObject(bm);
checked = TRUE;
}
}
if ((Item->hbmpItem)&& !( checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
{
MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
}
/* Draw the popup-menu arrow */
if (0 != (Item->fType & MF_POPUP))
{
HDC DcMem = CreateCompatibleDC(Dc);
HBITMAP OrigBitmap;
OrigBitmap = SelectObject(DcMem, StdMnArrow);
BitBlt(Dc, Rect.right - ArrowBitmapWidth - 1,
(y - ArrowBitmapHeight) / 2,
ArrowBitmapWidth, ArrowBitmapHeight,
DcMem, 0, 0, SRCCOPY);
SelectObject(DcMem, OrigBitmap);
DeleteDC(DcMem);
}
Rect.left += 4;
if( !(MenuInfo->dwStyle & MNS_NOCHECK))
Rect.left += CheckBitmapWidth;
Rect.right -= ArrowBitmapWidth;
}
else if (Item->hbmpItem) /* Draw the bitmap */
{
MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
}
/* No bitmap - process text if present */
if (Item->Text)
{
register int i = 0;
HFONT FontOld = NULL;
UINT uFormat = MenuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
: DT_LEFT | DT_VCENTER | DT_SINGLELINE;
if( !(MenuInfo->dwStyle & MNS_CHECKORBMP))
Rect.left += MenuInfo->maxBmpSize.cx;
if (0 != (Item->fState & MFS_DEFAULT))
{
FontOld = SelectObject(Dc, hMenuFontBold);
}
if (MenuBar)
{
Rect.left += MENU_BAR_ITEMS_SPACE / 2;
Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
}
if (Item->hbmpItem == HBMMENU_CALLBACK || MenuInfo->maxBmpSize.cx != 0 )
{
Rect.left += MenuInfo->maxBmpSize.cx;
Rect.right -= MenuInfo->maxBmpSize.cx;
}
Text = (PWCHAR) Item->dwTypeData;
if(Text)
{
for (i = 0; L'\0' != Text[i]; i++)
{
if (L'\t' == Text[i] || L'\b' == Text[i])
{
break;
}
}
}
if (0 != (Item->fState & MF_GRAYED))
{
if (0 == (Item->fState & MF_HILITE))
{
++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
DrawTextW(Dc, Text, i, &Rect, uFormat);
--Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
}
SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
}
DrawTextW(Dc, Text, i, &Rect, uFormat);
/* paint the shortcut text */
if (! MenuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
{
if (L'\t' == Text[i])
{
Rect.left = Item->XTab;
uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
else
{
Rect.right = Item->XTab;
uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
if (0 != (Item->fState & MF_GRAYED))
{
if (0 == (Item->fState & MF_HILITE))
{
++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
--Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
}
SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
}
DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
}
if (NULL != FontOld)
{
SelectObject(Dc, FontOld);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -