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