using System; using System.Windows; using System.Drawing; using System.Windows.Forms; using System.ComponentModel; using System.Drawing.Text; using System.Diagnostics; using System.Collections; namespace ControlSet { /// <summary> /// 自绘菜单 /// </summary> public class OwnerDrawMenu : MenuItem { private static Color backcolor; private static Color barcolor; private static Color selectioncolor; private static Color framecolor; private static int iconSize = SystemInformation.SmallIconSize.Width + 5; private static int itemHeight; private string shortcuttext = ""; private Image icon = null; private static int BITMAP_SIZE = 16; private static int STRIPE_WIDTH = iconSize + 5; public OwnerDrawMenu() : base() { OwnerDraw = true; } private OwnerDrawMenu(string name) : base(name) { OwnerDraw = true; } public OwnerDrawMenu(string name, EventHandler handler) : base(name, handler) { OwnerDraw = true; } private OwnerDrawMenu(string name, EventHandler handler, Shortcut shortcut) : base(name, handler, shortcut) { OwnerDraw = true; } private OwnerDrawMenu(MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string name, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, OwnerDrawMenu[] items) : base(mergeType, mergeOrder, shortcut, name, onClick, onPopup, onSelect, items) { OwnerDraw = true; } private OwnerDrawMenu(string name, Image img) : this(name) { OwnerDraw = true; icon = img; } private OwnerDrawMenu(string name, EventHandler handler, Image img) : this(name, handler) { OwnerDraw = true; icon = img; } private OwnerDrawMenu(string name, EventHandler handler, Shortcut shortcut, Image img) : this(name, handler, shortcut) { OwnerDraw = true; icon = img; } public Image Icon { get { return icon; } set { icon = value; } } private string ShortcutText { get { return shortcuttext; } set { shortcuttext = value; } } public Color SelectionColor { get { return selectioncolor; } set { selectioncolor = value; } } public Color BackColor { get { return backcolor; } set { backcolor = value; } } public Color BarColor { get { return barcolor; } set { barcolor = value; } } public Color FrameColor { get { return framecolor; } set { framecolor = value; } } protected override void OnMeasureItem(MeasureItemEventArgs e) { if (Shortcut != Shortcut.None) { string text = ""; int key = (int)Shortcut; int ch = key & 0xFF; if (((int)Keys.Control & key) > 0) text += "Ctrl+"; if (((int)Keys.Shift & key) > 0) text += "Shift+"; if (((int)Keys.Alt & key) > 0) text += "Alt+"; if (ch >= (int)Shortcut.F1 && ch <= (int)Shortcut.F12) text += "F" + (ch - (int)Shortcut.F1 + 1); else { if (Shortcut == Shortcut.Del) { text += "Del"; } else { text += (char)ch; } } shortcuttext = text; } if (Text == "-") { e.ItemHeight = 8; e.ItemWidth = 4; return; } bool topLevel = Parent == Parent.GetMainMenu(); string tempShortcutText = shortcuttext; if (topLevel) { tempShortcutText = ""; } int textwidth = (int)(e.Graphics.MeasureString(Text + tempShortcutText, SystemInformation.MenuFont).Width); int extraHeight = 4; e.ItemHeight = SystemInformation.MenuHeight + extraHeight; if (topLevel) e.ItemWidth = textwidth - 5; else e.ItemWidth = Math.Max(160, textwidth + 50); itemHeight = e.ItemHeight; base.OnMeasureItem(e); } protected override void OnDrawItem(DrawItemEventArgs e) { Graphics g = e.Graphics; Rectangle bounds = e.Bounds; bool selected = (e.State & DrawItemState.Selected) > 0; bool toplevel = (Parent == Parent.GetMainMenu()); bool hasicon = Icon != null; bool enabled = Enabled; DrawBackground(g, bounds, e.State, toplevel, hasicon, enabled); if (hasicon) DrawIcon(g, Icon, bounds, selected, Enabled, Checked); else { if (Checked) DrawCheckmark(g, bounds, selected); if (RadioCheck) DrawRadioCheckmark(g, bounds, selected); } if (Text == "-") { DrawSeparator(g, bounds); } else { DrawMenuText(g, bounds, Text, shortcuttext, Enabled, toplevel, e.State); } } private void DrawRadioCheckmark(Graphics g, Rectangle bounds, bool selected) { int checkTop = bounds.Top + (itemHeight - BITMAP_SIZE) / 2; int checkLeft = bounds.Left + (STRIPE_WIDTH - BITMAP_SIZE) / 2; ControlPaint.DrawMenuGlyph(g, new Rectangle(checkLeft, checkTop, BITMAP_SIZE, BITMAP_SIZE), MenuGlyph.Bullet); g.DrawRectangle(new Pen(framecolor), checkLeft - 1, checkTop - 1, BITMAP_SIZE + 1, BITMAP_SIZE + 1); } private void DrawCheckmark(Graphics g, Rectangle bounds, bool selected) { int checkTop = bounds.Top + (itemHeight - BITMAP_SIZE) / 2; int checkLeft = bounds.Left + (STRIPE_WIDTH - BITMAP_SIZE) / 2; ControlPaint.DrawMenuGlyph(g, new Rectangle(checkLeft, checkTop, BITMAP_SIZE, BITMAP_SIZE), MenuGlyph.Checkmark); g.DrawRectangle(new Pen(framecolor), checkLeft - 1, checkTop - 1, BITMAP_SIZE + 1, BITMAP_SIZE + 1); } private void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked) { int iconTop = bounds.Top + (itemHeight - BITMAP_SIZE) / 2; int iconLeft = bounds.Left + (STRIPE_WIDTH - BITMAP_SIZE) / 2; if (enabled) { if (selected) { ControlPaint.DrawImageDisabled(g, icon, iconLeft + 1, iconTop, Color.Black); g.DrawImage(icon, iconLeft, iconTop - 1); } else { g.DrawImage(icon, iconLeft + 1, iconTop); } } else { ControlPaint.DrawImageDisabled(g, icon, iconLeft + 1, iconTop, SystemColors.HighlightText); } } private void DrawSeparator(Graphics g, Rectangle bounds) { int y = bounds.Y + bounds.Height / 2; g.DrawLine(new Pen(SystemColors.ControlDark), bounds.X + iconSize + 7, y, bounds.X + bounds.Width - 2, y); } private void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon, bool enabled) { bool selected = (state & DrawItemState.Selected) > 0; if (selected || ((state & DrawItemState.HotLight) > 0)) { if (toplevel && selected) { bounds.Inflate(-1, 0); g.FillRectangle(new SolidBrush(barcolor), bounds); ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.SunkenOuter, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right | Border3DSide.Bottom); } else { if (toplevel) { bounds.Inflate(-1, 0); g.FillRectangle(new SolidBrush(barcolor), bounds); ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.RaisedInner, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right | Border3DSide.Bottom); } else if (enabled) { g.FillRectangle(new SolidBrush(selectioncolor), bounds); g.DrawRectangle(new Pen(framecolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); } else { g.FillRectangle(new SolidBrush(barcolor), bounds); bounds.X += STRIPE_WIDTH; bounds.Width -= STRIPE_WIDTH; g.FillRectangle(new SolidBrush(backcolor), bounds); } } } else { if (!toplevel) { g.FillRectangle(new SolidBrush(barcolor), bounds); bounds.X += STRIPE_WIDTH; bounds.Width -= STRIPE_WIDTH; g.FillRectangle(new SolidBrush(backcolor), bounds); } else { g.FillRectangle(SystemBrushes.Control, bounds); } } } private void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state) { StringFormat stringformat = new StringFormat(); stringformat.HotkeyPrefix = ((state & DrawItemState.NoAccelerator) > 0) ? HotkeyPrefix.Hide : HotkeyPrefix.Show; if (toplevel) { int index = text.IndexOf("&"); if (index != -1) { text = text.Remove(index, 1); } } int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width); int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2 : bounds.Left + iconSize + 10; int topGap = 7; if (toplevel) topGap = 2; int y = bounds.Top + topGap; Brush brush = null; if (!enabled) brush = new SolidBrush(SystemColors.GrayText); else brush = new SolidBrush(SystemColors.MenuText); g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat); if (!toplevel) { stringformat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Width - 10, bounds.Top + topGap, stringformat); } } } }