A complete ownerdraw menu class with RightToLeft support.
Add this class to your project and after designing the layout of your standard menu, use search and replace to replace 'System.Windows.Forms.MenuItem' with 'MenuItemEx'. You will then be able to assign colors and icons to each menu item in the project. Use this class for MDI projects or download the MenuSkinner component in the Controls section. The MenuSkinner is much simpler to use but there is a problem with Menus that unMerge which I have yet to find a solution for.
by: Mick Dohertys'
Add this class to your project and after designing the layout of your standard menu, use search and replace to replace 'System.Windows.Forms.MenuItem' with 'MenuItemEx'. You will then be able to assign colors and icons to each menu item in the project. Use this class for MDI projects or download the MenuSkinner component in the Controls section. The MenuSkinner is much simpler to use but there is a problem with Menus that unMerge which I have yet to find a solution for.
VB net Sample:
Imports System.ComponentModel Imports System.Runtime.InteropServices Imports System.Environment Imports System.ComponentModel.Design Public Class MenuitemEx Inherits MenuItem #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub 'UserControl overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() ' 'MenuitemEx ' Me.OwnerDraw = True End Sub #End Region #Region " XP Related InterOp " <DllImport("uxtheme.dll", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function IsAppThemed() As Boolean End Function <DllImport("user32.dll", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function GetSysColor(ByVal index As Integer) As Integer End Function Private Const COLOR_MENUBAR As Integer = 30 #End Region #Region " Custom Constructors " Sub New(ByVal caption As String) MyClass.New(caption, Nothing) End Sub Sub New(ByVal caption As String, ByVal [image] As Image) MyBase.New() m_Image = [image] Me.Text = caption End Sub #End Region #Region " Private Instance Variables " Private m_Image As Image = Nothing Private m_ItemColors As MenuItemColors = New MenuItemColors(Me) Private m_Font As Font = SystemInformation.MenuFont Private m_HiliteStyle As HiliteStyles = HiliteStyles.Flat Private m_ImageIndex As Integer = -1 Private m_Imagelist As ImageList = Nothing Private m_ShadowImage As Image Private m_IsXPThemed As Boolean = IsXPThemed ' ________________1______________ ' | | _________3_________ | ' | 2 | |_________4_________| | ' |____|__________________________| Private m_ItemRect As Rectangle '1 Private m_ImageRect As Rectangle '2 Private m_BackRect As Rectangle '3 Private m_TextRect As Rectangle '4 #End Region #Region " Custom Enum " Public Enum HiliteStyles [Flat] [Shadow] [Box] End Enum #End Region #Region " Properties " 'Image <Category("Appearance"), DefaultValue(GetType(Image), Nothing)> _ Public Property Image() As Image Get If IsNothing(m_Imagelist) = False Then If m_ImageIndex > -1 Then Return m_Imagelist.Images(m_ImageIndex) End If End If Return m_Image End Get Set(ByVal Value As Image) m_Image = Value End Set End Property 'ImageList <Category("Appearance"), DefaultValue(GetType(ImageList), Nothing)> _ Public Property ImageList() As ImageList Get Return m_Imagelist End Get Set(ByVal Value As ImageList) m_Imagelist = Value End Set End Property 'ImageIndex <Category("Appearance"), DefaultValue(-1), _ TypeConverter(GetType(ImageIndexConverter)), _ Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", GetType(System.Drawing.Design.UITypeEditor))> _ Public Property ImageIndex() As Integer Get If m_Imagelist Is Nothing Then m_ImageIndex = -1 End If Return m_ImageIndex End Get Set(ByVal Value As Integer) m_ImageIndex = Value End Set End Property 'ItemColors <Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _ Public Property ItemColors() As MenuItemColors Get Return m_ItemColors End Get Set(ByVal Value As MenuItemColors) m_ItemColors = Value End Set End Property 'Font <Category("Appearance"), _ Description("The Font that displays in this MenuItem.")> _ Public Property Font() As Font Get Return m_Font End Get Set(ByVal Value As Font) If Not m_Font.Equals(Value) Then If IsNothing(Value) Then ResetFont() Else m_Font = Value End If End If End Set End Property Private Function ShouldSerializeFont() As Boolean Return Not (m_Font.Equals(SystemInformation.MenuFont)) End Function Private Sub ResetFont() m_Font = SystemInformation.MenuFont End Sub 'HiliteStyle <Category("Behavior"), DefaultValue(GetType(HiliteStyles), "Flat")> _ Public Property HiliteStyle() As HiliteStyles Get Return m_HiliteStyle End Get Set(ByVal Value As HiliteStyles) m_HiliteStyle = Value End Set End Property Private ReadOnly Property IsXPThemed() As Boolean Get If OSVersion.Version.Major >= 5 And OSVersion.Version.Minor >= 1 Then Return IsAppThemed() End If End Get End Property Private ReadOnly Property RTLMenu() As Boolean Get If IsNothing(Me.GetContextMenu) Then Return CBool(Me.GetMainMenu.RightToLeft) Else Return CBool(Me.GetContextMenu.RightToLeft) End If End Get End Property #End Region #Region " Expandable Object Convertor " 'MenuItemColors <TypeConverter(GetType(MenuItemColorsStringConverter))> _ Public Class MenuItemColors Public Sub New(ByVal parent As MenuitemEx) owner = Parent End Sub Private Owner As MenuitemEx = Nothing Private m_StartColor As Color = Color.Ivory Private m_EndColor As Color = Color.PowderBlue Private m_ImageBarColor As Color = Color.PowderBlue Private m_HiliteColor As Color = Color.Moccasin Private m_HiliteBorderColor As Color = Color.Coral Private m_ForeColor As Color = Color.OrangeRed 'GradientStartColor <DefaultValue(GetType(Color), "Ivory")> _ Public Property GradientStartColor() As Color Get Return m_StartColor End Get Set(ByVal Value As Color) m_StartColor = Value updateProperties() End Set End Property 'GradientEndColor <DefaultValue(GetType(Color), "PowderBlue")> _ Public Property GradientEndColor() As Color Get Return m_EndColor End Get Set(ByVal Value As Color) m_EndColor = Value updateProperties() End Set End Property 'ImageBarColor <DefaultValue(GetType(Color), "PowderBlue")> _ Public Property ImageBarColor() As Color Get Return m_ImageBarColor End Get Set(ByVal Value As Color) m_ImageBarColor = Value updateProperties() End Set End Property 'HiliteColor <DefaultValue(GetType(Color), "Moccasin")> _ Public Property HiliteColor() As Color Get Return m_HiliteColor End Get Set(ByVal Value As Color) m_HiliteColor = Value updateProperties() End Set End Property 'HiliteBorderColor <DefaultValue(GetType(Color), "Coral")> _ Public Property HiliteBorderColor() As Color Get Return m_HiliteBorderColor End Get Set(ByVal Value As Color) m_HiliteBorderColor = Value updateProperties() End Set End Property 'ForeColor <DefaultValue(GetType(Color), "OrangeRed")> _ Public Property ForeColor() As Color Get Return m_ForeColor End Get Set(ByVal Value As Color) m_ForeColor = Value updateProperties() End Set End Property 'This method is necessary for the property to be deserialized 'upon reset, and caused me the biggest headache. Sub updateProperties() If Owner Is Nothing Then Return Dim ccs As IComponentChangeService = CType(Owner.GetService(GetType(IComponentChangeService)), IComponentChangeService) If ccs Is Nothing Then Return ccs.OnComponentChanged(Owner.ItemColors, Nothing, Nothing, Nothing) End Sub End Class 'MenuItemColorStringConvertor Friend Class MenuItemColorsStringConverter Inherits ExpandableObjectConverter Public Overloads Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object If destinationType Is GetType(String) Then Return "MenuItem Colors" End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function Public Overloads Overrides Function GetPropertiesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean Return True End Function Public Overloads Overrides Function GetProperties(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal value As Object, ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection If context.PropertyDescriptor.PropertyType.Name.Equals("MenuItemColors") Then Dim PropertyDescriptorCollection As System.ComponentModel.PropertyDescriptorCollection Dim propNames(5) As String PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(MenuItemColors), attributes) propNames(0) = "ImageBarColor" propNames(1) = "GradientStartColor" propNames(2) = "GradientEndColor" propNames(3) = "HiliteColor" propNames(4) = "HiliteBorderColor" propNames(5) = "ForeColor" Return PropertyDescriptorCollection.Sort(propNames) End If Return MyBase.GetProperties(context, value, attributes) End Function End Class #End Region Protected Overrides Sub OnMeasureItem(ByVal e As System.Windows.Forms.MeasureItemEventArgs) Dim ItemText As String = Text If ShowShortcut AndAlso Shortcut <> Shortcut.None Then Dim k As Keys = CType(Shortcut, Keys) ItemText += " " + TypeDescriptor.GetConverter(GetType(Keys)).ConvertToString(k) End If Dim sf As New StringFormat(StringFormatFlags.MeasureTrailingSpaces) sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide e.ItemWidth = CInt(e.Graphics.MeasureString(ItemText, m_Font, SizeF.Empty, sf).Width) If Me.Text = "-" Then e.ItemHeight = 3 ElseIf Not TypeOf Me.Parent Is MainMenu Then e.ItemHeight = 22 e.ItemWidth += 44 End If End Sub Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs) m_ItemRect = e.Bounds m_ImageRect = New Rectangle(e.Bounds.Location, New Size(24, e.Bounds.Height)) m_BackRect = New Rectangle(e.Bounds.Left + 24, e.Bounds.Top, e.Bounds.Width - 24, e.Bounds.Height) m_TextRect = New Rectangle(e.Bounds.Left + 34, e.Bounds.Top, e.Bounds.Width - 52, e.Bounds.Height) If RTLMenu Then m_ImageRect.Offset(e.Bounds.Width - 24, 0) m_BackRect.Offset(-24, 0) m_TextRect.Offset(-14, 0) End If If Text = "-" Then DrawSideBar(e.Graphics) DrawBackground(e.Graphics) DrawSeparator(e.Graphics) ElseIf Not TypeOf Me.Parent Is MainMenu Then DrawSideBar(e.Graphics) DrawBackground(e.Graphics) If CBool(e.State And DrawItemState.Selected) Then DrawHilite(e.Graphics) DrawImage(e.Graphics, CBool(e.State And DrawItemState.Selected) And (m_HiliteStyle = HiliteStyles.Shadow)) DrawText(e.Graphics, Not CBool(e.State And DrawItemState.NoAccelerator)) Else m_TextRect = e.Bounds DrawMenuBar(e.Graphics) If CBool(e.State And DrawItemState.Selected) OrElse _ CBool(e.State And DrawItemState.HotLight) Then DrawHilite(e.Graphics) End If DrawText(e.Graphics, Not CBool(e.State And DrawItemState.NoAccelerator)) End If End Sub #Region " Custom Methods " Sub DrawMenuBar(ByVal g As Graphics) Dim FillBrush As New SolidBrush(SystemColors.Menu) If m_IsXPThemed Then FillBrush.Color = ColorTranslator.FromOle(GetSysColor(COLOR_MENUBAR)) End If g.FillRectangle(FillBrush, m_ItemRect) FillBrush.Dispose() End Sub Sub DrawSeparator(ByVal g As Graphics) Dim DrawingPen As New Pen(m_ItemColors.ForeColor) Dim startpoint As New Point(m_TextRect.Left, m_TextRect.Top + 1) Dim endpoint As New Point(m_BackRect.Right - 1, m_BackRect.Top + 1) If RTLMenu Then startpoint.Offset(-20, 0) endpoint.Offset(-10, 0) End If g.DrawLine(DrawingPen, startpoint, endpoint) DrawingPen.Dispose() End Sub Sub DrawSideBar(ByVal g As Graphics) Dim DrawingBrush As New SolidBrush(m_ItemColors.ImageBarColor) g.FillRectangle(DrawingBrush, m_ImageRect) DrawingBrush.Dispose() End Sub Sub DrawBackground(ByVal g As Graphics) Dim FillBrush As Brush If RTLMenu Then FillBrush = New Drawing2D.LinearGradientBrush(m_BackRect, m_ItemColors.GradientEndColor, m_ItemColors.GradientStartColor, Drawing2D.LinearGradientMode.Horizontal) Else FillBrush = New Drawing2D.LinearGradientBrush(m_BackRect, m_ItemColors.GradientStartColor, m_ItemColors.GradientEndColor, Drawing2D.LinearGradientMode.Horizontal) End If g.FillRectangle(FillBrush, m_BackRect) FillBrush.Dispose() End Sub Sub DrawHilite(ByVal g As Graphics) Dim FillBrush As New SolidBrush(m_ItemColors.HiliteColor) Dim HiliteRect As Rectangle = m_ItemRect If m_HiliteStyle = HiliteStyles.Box AndAlso Not TypeOf Me.Parent Is MainMenu Then HiliteRect.Width -= 24 If Not RTLMenu Then HiliteRect.Offset(24, 0) BoxImage(g) End If g.FillRectangle(FillBrush, HiliteRect) Dim BorderPen As New Pen(m_ItemColors.HiliteBorderColor) HiliteRect.Width -= 1 HiliteRect.Height -= 1 g.DrawRectangle(BorderPen, HiliteRect) FillBrush.Dispose() BorderPen.Dispose() End Sub Sub BoxImage(ByVal g As Graphics) If Image Is Nothing Then Return Dim BorderPen As New Pen(ControlPaint.LightLight(m_ItemColors.ImageBarColor)) Dim BorderRect As Rectangle = m_ImageRect BorderRect.Inflate(-1, -1) g.DrawRectangle(BorderPen, BorderRect) BorderPen.Color = ControlPaint.Dark(m_ItemColors.ImageBarColor) g.DrawLine(BorderPen, BorderRect.Right - 1, BorderRect.Top, BorderRect.Right - 1, BorderRect.Bottom) g.DrawLine(BorderPen, BorderRect.Left, BorderRect.Bottom, BorderRect.Right - 1, BorderRect.Bottom) BorderPen.Dispose() End Sub Sub DrawText(ByVal g As Graphics, ByVal ShowHotKey As Boolean) Dim TextBrush As New SolidBrush(m_ItemColors.ForeColor) Dim sf As New StringFormat sf.LineAlignment = StringAlignment.Center sf.Alignment = StringAlignment.Near If ShowHotKey Then sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show Else sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide End If Dim ShorCutText As String If ShowShortcut AndAlso Shortcut <> Shortcut.None Then Dim k As Keys = CType(Shortcut, Keys) ShorCutText = TypeDescriptor.GetConverter(GetType(Keys)).ConvertToString(k) End If If RTLMenu Then sf.FormatFlags = StringFormatFlags.DirectionRightToLeft End If If TypeOf Me.Parent Is MainMenu Then sf.Alignment = StringAlignment.Center If Me.Enabled Then g.DrawString(Text, m_Font, TextBrush, RectangleF.op_Implicit(m_TextRect), sf) sf.Alignment = StringAlignment.Far g.DrawString(ShorCutText, m_Font, TextBrush, RectangleF.op_Implicit(m_TextRect), sf) Else ControlPaint.DrawStringDisabled(g, Text, m_Font, m_ItemColors.GradientEndColor, RectangleF.op_Implicit(m_TextRect), sf) sf.Alignment = StringAlignment.Far ControlPaint.DrawStringDisabled(g, ShorCutText, m_Font, m_ItemColors.GradientEndColor, RectangleF.op_Implicit(m_TextRect), sf) End If TextBrush.Dispose() sf.Dispose() End Sub Sub DrawImage(ByVal g As Graphics, ByVal Shadow As Boolean) If Image Is Nothing Then Return Dim Iconrect As Rectangle = m_ImageRect Iconrect.Inflate(-4, -4) If Shadow Then If m_ShadowImage Is Nothing Then m_ShadowImage = New Bitmap(CreateShadowImage(Image)) End If Iconrect.Offset(1, 1) g.DrawImage(m_ShadowImage, Iconrect) Iconrect.Offset(-2, -2) End If g.DrawImage(Image, Iconrect) End Sub Function CreateShadowImage(ByVal bmp As Image) As Bitmap Dim shadow As New Bitmap(bmp, 16, 16) Dim ShadowColor As Color = ControlPaint.Dark(m_ItemColors.HiliteColor) For x As Integer = 0 To 15 For y As Integer = 0 To 15 If shadow.GetPixel(x, y).A > 32 Then shadow.SetPixel(x, y, ShadowColor) End If Next Next Return shadow End Function #End Region 'didn't have to do this in C# Friend Shadows Function GetService(ByVal service As System.Type) As Object Return MyBase.GetService(service) End Function End Class
CSharp Sample:
using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.ComponentModel.Design; using System.Runtime.InteropServices; namespace Dotnetrix_Samples { /// <summary> /// Summary description for MenuItemEx. /// </summary> public class MenuItemEx : System.Windows.Forms.MenuItem { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public MenuItemEx() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); // TODO: Add any initialization after the InitializeComponent call m_ItemColors = new MenuItemColors(this); } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Component Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { // // MenuItemEx // this.OwnerDraw = true; } #endregion #region XP Related InterOp [DllImport("uxtheme.dll", CallingConvention=CallingConvention.Cdecl)] private static extern bool IsAppThemed(); [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int GetSysColor(int index); private const int COLOR_MENUBAR = 30; #endregion #region Custom Constructors public MenuItemEx(String caption) : this(caption,(Image)null) { } public MenuItemEx(String caption,Image image): base() { m_Image = image; this.Text = caption; } #endregion #region Private Instance Variables private Image m_Image = null; private MenuItemColors m_ItemColors; private Font m_Font = SystemInformation.MenuFont; private HiliteStyles m_HiliteStyle = HiliteStyles.Flat; private int m_ImageIndex = -1; private ImageList m_Imagelist = null; private Image m_ShadowImage = null; private bool m_IsXPThemed = IsXPThemed; // ________________1______________ // | | _________3_________ | // | 2 | |_________4_________| | // |____|__________________________| private Rectangle m_ItemRect; //1 private Rectangle m_ImageRect; //2 private Rectangle m_BackRect; //3 private Rectangle m_TextRect; //4 #endregion #region Custom Enum public enum HiliteStyles { Flat, Shadow, Box } #endregion #region Properties //Image [Category("Appearance"), DefaultValue(typeof(Image), null)] public Image image { get { if (m_Imagelist != null) { if (m_ImageIndex > -1) return m_Imagelist.Images[m_ImageIndex]; } return m_Image; } set { m_Image = value; } } //ImageList [Category("Appearance"), DefaultValue(typeof(ImageList), null)] public ImageList imageList { get { return m_Imagelist; } set { m_Imagelist = value; } } //ImageIndex [Category("Appearance"), DefaultValue(-1), TypeConverter(typeof(ImageIndexConverter)), Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", typeof(System.Drawing.Design.UITypeEditor))] public int ImageIndex { get { if (m_Imagelist == null) m_ImageIndex = -1; return m_ImageIndex; } set { m_ImageIndex = value; } } //ItemColors [Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [RefreshProperties(RefreshProperties.All)] public MenuItemColors ItemColors { get { return m_ItemColors; } set { m_ItemColors = value; } } //Font [Category("Appearance"),Description("The Font that displays in this MenuItem.")] public Font font { get { return m_Font; } set { if (!m_Font.Equals(value)) { if (value != null) ResetFont(); else m_Font = value; } } } private bool ShouldSerializeFont() { return !m_Font.Equals(SystemInformation.MenuFont); } private void ResetFont() { m_Font = SystemInformation.MenuFont; } //HiliteStyle [Category("Behavior"), DefaultValue(typeof(HiliteStyles), "Flat")] public HiliteStyles HiliteStyle { get { return m_HiliteStyle; } set { m_HiliteStyle = value; } } private static bool IsXPThemed { get { if (Environment.OSVersion.Version.Major >= 5 && Environment.OSVersion.Version.Minor >= 1) return IsAppThemed(); return false; } } private bool RTLMenu { get { if (GetContextMenu() == null) return (bool)(GetMainMenu().RightToLeft == RightToLeft.Yes); else return (bool)(GetContextMenu().RightToLeft == RightToLeft.Yes); } } #endregion #region Expandable Object Convertor //MenuItemColors [TypeConverter(typeof(MenuItemColorsStringConverter))] public class MenuItemColors { public MenuItemColors(MenuItemEx parent) : base() { owner = parent; } private MenuItemEx owner; private Color m_StartColor = Color.Ivory; private Color m_EndColor = Color.PowderBlue; private Color m_ImageBarColor = Color.PowderBlue; private Color m_HiliteColor = Color.Moccasin; private Color m_HiliteBorderColor = Color.Coral; private Color m_ForeColor = Color.OrangeRed; //GradientStartColor [DefaultValue(typeof(Color), "Ivory")] public Color GradientStartColor { get { return m_StartColor; } set { m_StartColor = value; updateProperties(); } } //GradientEndColor [DefaultValue(typeof(Color), "PowderBlue")] public Color GradientEndColor { get { return m_EndColor; } set { m_EndColor = value; updateProperties(); } } //ImageBarColor [DefaultValue(typeof(Color), "PowderBlue")] public Color ImageBarColor { get { return m_ImageBarColor; } set { m_ImageBarColor = value; updateProperties(); } } //HiliteColor [DefaultValue(typeof(Color), "Moccasin")] public Color HiliteColor { get { return m_HiliteColor; } set { m_HiliteColor = value; updateProperties(); } } //HiliteBorderColor [DefaultValue(typeof(Color), "Coral")] public Color HiliteBorderColor { get { return m_HiliteBorderColor; } set { m_HiliteBorderColor = value; updateProperties(); } } //ForeColor [DefaultValue(typeof(Color), "OrangeRed")] public Color ForeColor { get { return m_ForeColor; } set { m_ForeColor = value; updateProperties(); } } //This method is necessary for the property to be deserialized //upon reset, and caused me the biggest headache. void updateProperties() { if (owner == null) return; IComponentChangeService ccs = (IComponentChangeService) owner.GetService(typeof(IComponentChangeService)); if (ccs == null) return; ccs.OnComponentChanged(owner.ItemColors, null, null, null); } } //MenuItemColorStringConvertor internal class MenuItemColorsStringConverter : ExpandableObjectConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return false; } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string) && value is MenuItemColors) return "MenuItem Colors"; return base.ConvertTo (context, culture, value, destinationType); } public override bool GetPropertiesSupported(ITypeDescriptorContext context) { return true; } public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { if (context.PropertyDescriptor.PropertyType.Name.Equals("MenuItemColors")) { System.ComponentModel.PropertyDescriptorCollection propertyDescriptorCollection; string[] propNames = new string[5]; propertyDescriptorCollection = TypeDescriptor.GetProperties(typeof(MenuItemColors),attributes); propNames[0] = @"ImageBarColor"; propNames[1] = @"GradientStartColor"; propNames[2] = @"GradientEndColor"; propNames[3] = @"HiliteColor"; propNames[4] = @"HiliteBorderColor"; //for some reason setting the last element stops the Property //expanding in C# but not in VB. Not that it matters since //it's the only property left and so will be auto sorted. //propNames[5] = @"ForeColor"; return propertyDescriptorCollection.Sort(propNames); } return base.GetProperties(context, value, attributes); } } #endregion protected override void OnMeasureItem(MeasureItemEventArgs e) { String ItemText = Text; if (ShowShortcut && Shortcut != Shortcut.None) { Keys k = (Keys)Shortcut; ItemText += " " + TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(k); } StringFormat sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces); sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide; e.ItemWidth = (int)e.Graphics.MeasureString(ItemText, m_Font, SizeF.Empty, sf).Width; if (Text == "-") e.ItemHeight = 3; else if (this.Parent is MainMenu == false) { e.ItemHeight = 22; e.ItemWidth += 44; } } protected override void OnDrawItem(DrawItemEventArgs e) { m_ItemRect = e.Bounds; m_ImageRect = new Rectangle(e.Bounds.Location, new Size(24, e.Bounds.Height)); m_BackRect = new Rectangle(e.Bounds.Left + 24, e.Bounds.Top, e.Bounds.Width - 24, e.Bounds.Height); m_TextRect = new Rectangle(e.Bounds.Left + 34, e.Bounds.Top, e.Bounds.Width - 52, e.Bounds.Height); if (RTLMenu) { m_ImageRect.Offset(e.Bounds.Width - 24, 0); m_BackRect.Offset(-24, 0); m_TextRect.Offset(-14, 0); } if (Text == "-") { DrawSideBar(e.Graphics); DrawBackground(e.Graphics); DrawSeparator(e.Graphics); } else if(Parent is MainMenu == false) { DrawSideBar(e.Graphics); DrawBackground(e.Graphics); if (System.Convert.ToBoolean(e.State & DrawItemState.Selected)) DrawHilite(e.Graphics); DrawImage(e.Graphics, ((System.Convert.ToBoolean(e.State & DrawItemState.Selected) && (m_HiliteStyle == HiliteStyles.Shadow)))); DrawText(e.Graphics, !System.Convert.ToBoolean(e.State & DrawItemState.NoAccelerator)); } else { m_TextRect = e.Bounds; DrawMenuBar(e.Graphics); if (System.Convert.ToBoolean(e.State & DrawItemState.Selected) || System.Convert.ToBoolean(e.State & DrawItemState.HotLight)) DrawHilite(e.Graphics); DrawText(e.Graphics, !System.Convert.ToBoolean(e.State & DrawItemState.NoAccelerator)); } } #region Custom Methods void DrawMenuBar(Graphics g) { SolidBrush FillBrush = new SolidBrush(SystemColors.Menu); if (m_IsXPThemed) FillBrush.Color = ColorTranslator.FromOle(GetSysColor(COLOR_MENUBAR)); g.FillRectangle(FillBrush, m_ItemRect); FillBrush.Dispose(); } void DrawSeparator(Graphics g) { Pen DrawingPen = new Pen(m_ItemColors.ForeColor); Point startpoint = new Point(m_TextRect.Left, m_TextRect.Top + 1); Point endpoint = new Point(m_BackRect.Right - 1, m_BackRect.Top + 1); if (RTLMenu) { startpoint.Offset(-20, 0); endpoint.Offset(-10, 0); } g.DrawLine(DrawingPen, startpoint, endpoint); DrawingPen.Dispose(); } void DrawSideBar(Graphics g) { SolidBrush DrawingBrush = new SolidBrush(m_ItemColors.ImageBarColor); g.FillRectangle(DrawingBrush, m_ImageRect); DrawingBrush.Dispose(); } void DrawBackground(Graphics g) { Brush FillBrush; if (RTLMenu) FillBrush = new LinearGradientBrush(m_BackRect, m_ItemColors.GradientEndColor, m_ItemColors.GradientStartColor, LinearGradientMode.Horizontal); else FillBrush = new LinearGradientBrush(m_BackRect, m_ItemColors.GradientStartColor, m_ItemColors.GradientEndColor, LinearGradientMode.Horizontal); g.FillRectangle(FillBrush, m_BackRect); FillBrush.Dispose(); } void DrawHilite(Graphics g) { SolidBrush FillBrush = new SolidBrush(m_ItemColors.HiliteColor); Rectangle HiliteRect = m_ItemRect; if (m_HiliteStyle == HiliteStyles.Box && Parent is MainMenu == false) { HiliteRect.Width -= 24; if (!RTLMenu) HiliteRect.Offset(24, 0); BoxImage(g); } g.FillRectangle(FillBrush, HiliteRect); Pen BorderPen = new Pen(m_ItemColors.HiliteBorderColor); HiliteRect.Width -= 1; HiliteRect.Height -= 1; g.DrawRectangle(BorderPen, HiliteRect); FillBrush.Dispose(); BorderPen.Dispose(); } void BoxImage(Graphics g) { if (image == null) return; Pen BorderPen = new Pen(ControlPaint.LightLight(m_ItemColors.ImageBarColor)); Rectangle BorderRect = m_ImageRect; BorderRect.Inflate(-1, -1); g.DrawRectangle(BorderPen, BorderRect); BorderPen.Color = ControlPaint.Dark(m_ItemColors.ImageBarColor); g.DrawLine(BorderPen, BorderRect.Right - 1, BorderRect.Top, BorderRect.Right - 1, BorderRect.Bottom); g.DrawLine(BorderPen, BorderRect.Left, BorderRect.Bottom, BorderRect.Right - 1, BorderRect.Bottom); BorderPen.Dispose(); } void DrawText(Graphics g, bool ShowHotKey) { SolidBrush TextBrush = new SolidBrush(m_ItemColors.ForeColor); StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center; sf.Alignment = StringAlignment.Near; if (ShowHotKey) sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show; else sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide; String ShorCutText = ""; if (ShowShortcut && Shortcut != Shortcut.None) { Keys k = (Keys)Shortcut; ShorCutText = TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(k); } if (RTLMenu) sf.FormatFlags = StringFormatFlags.DirectionRightToLeft; if (Parent is MainMenu) sf.Alignment = StringAlignment.Center; if (Enabled) { g.DrawString(Text, m_Font, TextBrush, RectangleF.op_Implicit(m_TextRect), sf); sf.Alignment = StringAlignment.Far; g.DrawString(ShorCutText, m_Font, TextBrush, RectangleF.op_Implicit(m_TextRect), sf); } else { ControlPaint.DrawStringDisabled(g, Text, m_Font, m_ItemColors.GradientEndColor, RectangleF.op_Implicit(m_TextRect), sf); sf.Alignment = StringAlignment.Far; ControlPaint.DrawStringDisabled(g, ShorCutText, m_Font, m_ItemColors.GradientEndColor, RectangleF.op_Implicit(m_TextRect), sf); } TextBrush.Dispose(); sf.Dispose(); } void DrawImage(Graphics g, bool Shadow) { if (image == null) return; Rectangle Iconrect = m_ImageRect; Iconrect.Inflate(-4, -4); if (Shadow) { if (m_ShadowImage == null) m_ShadowImage = new Bitmap(CreateShadowImage(image)); Iconrect.Offset(1, 1); g.DrawImage(m_ShadowImage, Iconrect); Iconrect.Offset(-2, -2); } g.DrawImage(image, Iconrect); } Bitmap CreateShadowImage(Image bmp) { Bitmap shadow = new Bitmap(bmp, 16, 16); Color ShadowColor = ControlPaint.Dark(m_ItemColors.HiliteColor); for (int x = 0; x<=15; x++) { for (int y = 0; y<=15; y++) { if (shadow.GetPixel(x, y).A > 32) shadow.SetPixel(x, y, ShadowColor); } } return shadow; } #endregion } }
by: Mick Dohertys'
2 comments:
in a form can you please post a sampledemo in vb net thanks.
problem to use class in a form when you replace by menuitem....?????
Post a Comment