Publicado el 26/Dic/2005
Actualizado el 26/Dic/2005
Autor: Guillermo 'guille' Som
Aquí te muestro el código de la clase RichMenuItem, con esa clase podrás crear elementos de menús que utilicen imágens, y de una forma bastante fácil, por supuesto esta clase solo es necesaria para las versiones 2002 y 2003 de Visual Basic y de C#, ya que la versión 2005 incluye menús en los que se pueden indicar las imágenes a usar.
Del código mostrado, la clase de C# es la original incluida en SharpDevelop, pero la de Visual Basic está modificada para aceptar otras propiedades y formas de mostrarlo, (lee los comentarios para saber cuales son esas diferencias).
Al final de esta página tienes la autorización del autor de la clase de C# para que la publique sin estar atado a la licencia GPL que se aplica al proyecto SharpDevelop y a cada uno de sus componentes.
En esta otra página tienes un ejemplo para Visual Basic 2003 de cómo usar esa clase.
En ese mismo ejemplo puedes encontrar una clase para extraer iconos desde una imagen con varios iconos, esas imágenes serán las que se usen en los menús.
En esa página con el ejemplo, también hay una clase para seleccionar el dibujo a mostrar a partir de una imagen con varios iconos (también se incluye esa imagen en esa página), de forma que sea fácil indicar el icono que quieres usar.Espero que lo disfrutes.
Nos vemos.
Guillermo
El código para VB .NET
Este es el código de la clase RichMenuItem con algunas modificaciones sobre el original de C#.
'------------------------------------------------------------------------------ ' RichMenuItem.vb (15/Ene/02) ' Basado en RichMenuItem.cs de Mike Krueger autor de SharpDevelop ' ' Revisado 17/Jun/2004 Nuevo estilo de menús (Office2003) ' La banda de los menús la hago más ancha (sólo Office2003) ' Al crear la instancia se puede indicar el icono ' Revisado 19/Jun/2004 Propiedad compartida para el estilo de los menús ' Revisado 20/Jun/2004 Añado propiedad Description para mostrar la info del menú ' ' ©Guillermo 'guille' Som, 2002-2004 '------------------------------------------------------------------------------ ' Este código, al igual que el original, es libre y se puede redistribuir ' y/o modificar bajo los términos de la GNU General Public License publicada ' por Free Software Foundation versión 2 o posterior (si así lo estimas oportuno) '------------------------------------------------------------------------------ '// RichMenuItem.cs '// Copyright (c) 2001 Mike Krueger '// '// This program is free software; you can redistribute it and/or modify '// it under the terms of the GNU General Public License as published by '// the Free Software Foundation; either version 2 of the License, or '// (at your option) any later version. '// '// This program is distributed in the hope that it will be useful, '// but WITHOUT ANY WARRANTY; without even the implied warranty of '// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the '// GNU General Public License for more details. '// '// You should have received a copy of the GNU General Public License '// along with this program; if not, write to the Free Software '// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA '------------------------------------------------------------------------------ Option Strict On Imports Microsoft.VisualBasic Imports System Imports System.Drawing Imports System.Diagnostics Imports System.Drawing.Text Imports System.Drawing.Imaging Imports System.Windows.Forms 'Namespace elGuille.Components Public Class RichMenuItem : Inherits MenuItem Private Shared mnuStyle As IconMenuStyle = IconMenuStyle.VSNet Public Shared Property DefaultMenuStyle() As IconMenuStyle Get Return mnuStyle End Get Set(ByVal value As IconMenuStyle) mnuStyle = value End Set End Property ' Private _shortcuttext As String = "" Private _stringformat As StringFormat = New StringFormat Private _icon As Bitmap = Nothing Private _style As MenuItemStyleDrawer = Nothing Private _menustyle As IconMenuStyle = IconMenuStyle.VSNet ' Private shortcuttextwidth As Integer ' ' Descripción para usar en las barras de estado, etc. (20/Jun/04) Private _description As String Public Property Description() As String Get Return _description End Get Set(ByVal value As String) _description = value End Set End Property ' Public Shadows Function CloneMenu() As RichMenuItem Dim rmnu As New RichMenuItem(Me.Icon, Me.Text) rmnu.Checked = Me.Checked Return rmnu End Function Public Shadows Function CloneMenu(ByVal handler As EventHandler) As RichMenuItem Dim rmnu As New RichMenuItem(Me.Icon, Me.Text, handler, Me.Description) rmnu.Checked = Me.Checked Return rmnu End Function Public Shadows Function CloneMenu(ByVal handler As EventHandler, ByVal description As String) As RichMenuItem Dim rmnu As New RichMenuItem(Me.Icon, Me.Text, handler, description) rmnu.Checked = Me.Checked Return rmnu End Function ' Public Property MenuStyle() As IconMenuStyle Get Return _menustyle End Get Set(ByVal value As IconMenuStyle) ' asignar la variable compartida, (19/Jun/04) ' para que los nuevos menús usen el último estilo mnuStyle = value Select Case value Case IconMenuStyle.Office2000 _style = New Office2000Style OwnerDraw = True Case IconMenuStyle.Office2003 _style = New Office2003Style OwnerDraw = True Case IconMenuStyle.VSNet _style = New VSNetStyle OwnerDraw = True Case Else _style = Nothing OwnerDraw = False End Select End Set End Property ' Public Overloads Property ShortCutText() As String Get Return _shortcuttext End Get Set(ByVal Value As String) _shortcuttext = Value End Set End Property ' Public Property Icon() As Bitmap Get Return _icon End Get Set(ByVal Value As Bitmap) _icon = Value End Set End Property ' Public Sub New() MyBase.New() MenuStyle = mnuStyle End Sub ' ' Sin estilo ni icono Public Sub New(ByVal text As String) MyBase.New(text) MenuStyle = mnuStyle End Sub Public Sub New(ByVal text As String, ByVal items As RichMenuItem()) MyBase.New(text, items) MenuStyle = mnuStyle End Sub Public Sub New(ByVal text As String, ByVal handler As EventHandler) MyBase.New(text, handler) MenuStyle = mnuStyle End Sub Public Sub New(ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut) Me.New(text, handler) Me.Shortcut = shortcut MenuStyle = mnuStyle End Sub ' ' Usando el estilo en el primer parámetro Public Sub New(ByVal style As IconMenuStyle) MyBase.New() MenuStyle = style End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String) MyBase.New(text) MenuStyle = style End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal items As RichMenuItem()) MyBase.New(text, items) MenuStyle = style End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler) MyBase.New(text, handler) MenuStyle = style End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut) Me.New(style, text, handler) Me.Shortcut = shortcut End Sub ' ' con iconos y estilo (17/Jun/04) Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String) MyBase.New(text) MenuStyle = style Me.Icon = icono End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal items As RichMenuItem()) MyBase.New(text, items) MenuStyle = style Me.Icon = icono End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler) MyBase.New(text, handler) MenuStyle = style Me.Icon = icono End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut) Me.New(icono, style, text, handler) Me.Shortcut = shortcut End Sub ' ' con iconos sin estilo de menú (19/Jun/04) Public Sub New(ByVal icono As Bitmap, ByVal text As String) MyBase.New(text) Me.Icon = icono MenuStyle = mnuStyle End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal items As RichMenuItem()) MyBase.New(text, items) Me.Icon = icono MenuStyle = mnuStyle End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal handler As EventHandler) MyBase.New(text, handler) Me.Icon = icono MenuStyle = mnuStyle End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut) Me.New(icono, text, handler) Me.Shortcut = shortcut MenuStyle = mnuStyle End Sub ' ' constructores con la descripción Public Sub New(ByVal text As String, ByVal description As String) MyBase.New(text) MenuStyle = mnuStyle _description = description End Sub Public Sub New(ByVal text As String, ByVal items As RichMenuItem(), ByVal description As String) MyBase.New(text, items) MenuStyle = mnuStyle _description = description End Sub Public Sub New(ByVal text As String, ByVal handler As EventHandler, ByVal description As String) MyBase.New(text, handler) MenuStyle = mnuStyle _description = description End Sub Public Sub New(ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut, ByVal description As String) Me.New(text, handler, description) Me.Shortcut = shortcut MenuStyle = mnuStyle End Sub ' ' Usando el estilo en el primer parámetro 'Public Sub New(ByVal style As IconMenuStyle, ByVal description As String) ' MyBase.New() ' MenuStyle = style ' _description = description 'End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal description As String) MyBase.New(text) MenuStyle = style _description = description End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal items As RichMenuItem(), ByVal description As String) MyBase.New(text, items) MenuStyle = style _description = description End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal description As String) MyBase.New(text, handler) MenuStyle = style _description = description End Sub Public Sub New(ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut, ByVal description As String) Me.New(style, text, handler, description) Me.Shortcut = shortcut End Sub ' ' con iconos y estilo (17/Jun/04) Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal description As String) MyBase.New(text) MenuStyle = style Me.Icon = icono _description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal items As RichMenuItem(), ByVal description As String) MyBase.New(text, items) MenuStyle = style Me.Icon = icono _description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal description As String) MyBase.New(text, handler) MenuStyle = style Me.Icon = icono _description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal style As IconMenuStyle, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut, ByVal description As String) Me.New(icono, style, text, handler, description) Me.Shortcut = shortcut End Sub ' ' con iconos sin estilo de menú (19/Jun/04) Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal description As String) MyBase.New(text) Me.Icon = icono MenuStyle = mnuStyle _description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal items As RichMenuItem(), ByVal description As String) MyBase.New(text, items) Me.Icon = icono MenuStyle = mnuStyle description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal handler As EventHandler, ByVal description As String) MyBase.New(text, handler) Me.Icon = icono MenuStyle = mnuStyle _description = description End Sub Public Sub New(ByVal icono As Bitmap, ByVal text As String, ByVal handler As EventHandler, ByVal shortcut As Shortcut, ByVal description As String) Me.New(icono, text, handler, description) Me.Shortcut = shortcut MenuStyle = mnuStyle End Sub ' ' Protected Overrides Sub OnMeasureItem(ByVal e As MeasureItemEventArgs) MyBase.OnMeasureItem(e) '// make shortcut text If (Shortcut <> Shortcut.None) Then Dim text As String = "" Dim key As Integer = Shortcut Dim ch As Integer = key And &HFF If ((Keys.Control And key) > 0) Then _ text &= "Ctrl+" If ((Keys.Shift And key) > 0) Then _ text &= "Shift+" If ((Keys.Alt And key) > 0) Then _ text &= "Alt+" If (ch >= Shortcut.F1 And ch <= Shortcut.F12) Then text &= "F" & (ch - Shortcut.F1 + 1) ElseIf ((Keys.Insert And key) = Keys.Insert) Then text &= "Ins" Else ' mostrar la letra del acceso (17/Jun/04) text &= ChrW(ch) End If _shortcuttext = text End If If (MenuStyle <> IconMenuStyle.Standard) Then If (text = "-") Then e.ItemHeight = 8 e.ItemWidth = 4 Exit Sub 'Return End If Dim textwidth As Integer = CType(e.Graphics.MeasureString(text, SystemInformation.MenuFont).Width, Integer) shortcuttextwidth = CType(e.Graphics.MeasureString(ShortCutText, SystemInformation.MenuFont).Width, Integer) textwidth += shortcuttextwidth e.ItemHeight = SystemInformation.MenuHeight If (Parent Is Parent.GetMainMenu()) Then e.ItemWidth = textwidth - 5 '// 5 is a magic number :) Else e.ItemWidth = Math.Max(160, textwidth + 15) End If End If End Sub ' Protected Overrides Sub OnSelect(ByVal e As EventArgs) MyBase.OnSelect(e) End Sub ' Protected Overrides Sub OnDrawItem(ByVal e As DrawItemEventArgs) MyBase.OnDrawItem(e) Dim g As Graphics = e.Graphics Dim bounds As Rectangle = e.Bounds Dim selected As Boolean = (e.State And DrawItemState.Selected) > 0 Dim toplevel As Boolean = (Parent Is Parent.GetMainMenu()) Dim hasicon As Boolean = Not (Icon Is Nothing) _style.DrawBackground(g, bounds, e.State, toplevel, hasicon) If (hasicon) Then _style.DrawIcon(g, Icon, bounds, selected, Enabled, Checked) ElseIf (Checked) Then _style.DrawCheckmark(g, bounds, selected) End If If (Text = "-") Then _style.DrawSeparator(g, bounds) Else _style.DrawMenuText(g, bounds, Text, ShortCutText, Enabled, toplevel, e.State) End If End Sub End Class ' '--- ' Public Enum IconMenuStyle Standard Office2000 Office2003 VSNet End Enum Public Interface MenuItemStyleDrawer Sub DrawCheckmark(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal selected As Boolean) Sub DrawIcon(ByVal g As Graphics, ByVal icon As Image, ByVal bounds As Rectangle, ByVal selected As Boolean, ByVal enabled As Boolean, ByVal ischecked As Boolean) Sub DrawSeparator(ByVal g As Graphics, ByVal bounds As Rectangle) Sub DrawBackground(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal state As DrawItemState, ByVal toplevel As Boolean, ByVal hasicon As Boolean) Sub DrawMenuText(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal text As String, ByVal shortcut As String, ByVal enabled As Boolean, ByVal toplevel As Boolean, ByVal state As DrawItemState) End Interface ' Nueva clase al estilo de Office2003 (17/Jun/04) ' Sólo los colores, sin efectos de degradados... Public Class Office2003Style : Implements MenuItemStyleDrawer Shared bgcolor As Color = Color.WhiteSmoke ' El color de fondo de los menús Dim ibgcolor As Color = Color.FromArgb(200, 215, 240) ' El color de la banda izquierda de los menús Shared sbcolor As Color = Color.FromArgb(255, 236, 196) ' color de fondo del elemento seleccionado Dim sbbcolor As Color = Color.FromArgb(60, 96, 192) ' Color alrededor de la selección ' Dim TEXTSTART As Integer = 24 '20 ' Public Shared ReadOnly Property BackColor() As Color Get Return bgcolor End Get End Property Public Shared ReadOnly Property SelectedBackColor() As Color Get Return sbcolor End Get End Property ' Public Sub DrawCheckmark(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal selected As Boolean) Implements MenuItemStyleDrawer.DrawCheckmark 'ControlPaint.DrawMenuGlyph(g, New Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark) 'g.DrawRectangle(New Pen(sbbcolor), bounds.X + 1, bounds.Y + 1, 14 + 1, 14 + 1) ' If selected = False Then g.FillRectangle(New Pen(Color.Gold).Brush, bounds.X + 2, bounds.Y + 2, 14 + 2, 14 + 1) End If g.DrawString("v", New Font(SystemInformation.MenuFont, FontStyle.Bold), New Pen(SystemColors.MenuText).Brush, bounds.X + 2, bounds.Y + 2) ' End Sub Public Sub DrawIcon(ByVal g As Graphics, ByVal icon As Image, ByVal bounds As Rectangle, ByVal selected As Boolean, ByVal enabled As Boolean, ByVal ischecked As Boolean) Implements MenuItemStyleDrawer.DrawIcon If enabled Then If selected Then ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, Color.Black) g.DrawImage(icon, bounds.Left + 1, bounds.Top + 1) Else g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2) End If Else ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.HighlightText) End If End Sub Public Sub DrawSeparator(ByVal g As Graphics, ByVal bounds As Rectangle) Implements MenuItemStyleDrawer.DrawSeparator Dim y As Integer = CType(bounds.Y + bounds.Height / 2, Integer) g.DrawLine(New Pen(SystemColors.ControlDark), bounds.X + SystemInformation.SmallIconSize.Width + 7, y, bounds.X + bounds.Width - 2, y) End Sub Public Sub DrawBackground(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal state As DrawItemState, ByVal toplevel As Boolean, ByVal hasicon As Boolean) Implements MenuItemStyleDrawer.DrawBackground Dim selected As Boolean = (state And DrawItemState.Selected) > 0 If (selected OrElse ((state And DrawItemState.HotLight) > 0)) Then If (toplevel AndAlso selected) Then '// draw toplevel, selected menuitem g.FillRectangle(New SolidBrush(ibgcolor), bounds) ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top Or Border3DSide.Left Or Border3DSide.Right) Else '// draw menuitem, selected OR toplevel, hotlighted g.FillRectangle(New SolidBrush(sbcolor), bounds) g.DrawRectangle(New Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1) End If Else If (Not toplevel) Then '// draw menuitem, unselected g.FillRectangle(New SolidBrush(ibgcolor), bounds) bounds.X += 16 + 5 bounds.Width -= 16 + 5 g.FillRectangle(New SolidBrush(bgcolor), bounds) Else '// draw toplevel, unselected menuitem g.FillRectangle(SystemBrushes.Control, bounds) End If End If End Sub Public Sub DrawMenuText(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal text As String, ByVal shortcut As String, ByVal enabled As Boolean, ByVal toplevel As Boolean, ByVal state As DrawItemState) Implements MenuItemStyleDrawer.DrawMenuText Dim stringformat As StringFormat = New StringFormat stringformat.HotkeyPrefix = CType(IIf(((state And DrawItemState.NoAccelerator) > 0), HotkeyPrefix.Hide, HotkeyPrefix.Show), HotkeyPrefix) Dim textwidth As Integer = CType(g.MeasureString(text, SystemInformation.MenuFont).Width, Integer) Dim shortcutwidth As Integer = CType(g.MeasureString(shortcut, SystemInformation.MenuFont).Width, Integer) Dim x As Integer = CType(IIf(toplevel, bounds.Left + (bounds.Width - textwidth) / 2, bounds.Left + TEXTSTART), Integer) Dim y As Integer = bounds.Top + 2 Dim brush As Brush = Nothing If enabled Then brush = New SolidBrush(SystemColors.MenuText) Else brush = New SolidBrush(Color.FromArgb(120, SystemColors.MenuText)) End If g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat) g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat) End Sub End Class Public Class Office2000Style : Implements MenuItemStyleDrawer Dim TEXTSTART As Integer = 20 ' Public Shared ReadOnly Property BackColor() As Color Get Return SystemColors.Menu End Get End Property Public Shared ReadOnly Property SelectedBackColor() As Color Get Return SystemColors.Highlight End Get End Property ' Public Sub DrawCheckmark(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal selected As Boolean) Implements MenuItemStyleDrawer.DrawCheckmark ControlPaint.DrawMenuGlyph(g, New Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark) End Sub Public Sub DrawIcon(ByVal g As Graphics, ByVal icon As Image, ByVal bounds As Rectangle, ByVal selected As Boolean, ByVal enabled As Boolean, ByVal ischecked As Boolean) Implements MenuItemStyleDrawer.DrawIcon If (enabled) Then g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2) Else ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.Control) End If If (selected) Then _ ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, icon.Width + 3, icon.Height + 3, Border3DStyle.RaisedInner) End Sub Public Sub DrawSeparator(ByVal g As Graphics, ByVal bounds As Rectangle) Implements MenuItemStyleDrawer.DrawSeparator ControlPaint.DrawBorder3D(g, bounds.X, bounds.Y + 2, bounds.Width, 3, Border3DStyle.Etched, Border3DSide.Top) End Sub Public Sub DrawBackground(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal state As DrawItemState, ByVal toplevel As Boolean, ByVal hasicon As Boolean) Implements MenuItemStyleDrawer.DrawBackground Dim selected As Boolean = (state And DrawItemState.Selected) > 0 If (selected OrElse ((state And DrawItemState.HotLight) > 0)) Then If (toplevel) Then '// g.FillRectangle(SystemBrushes.Highlight, bounds); ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, CType(IIf(selected, Border3DStyle.SunkenOuter, Border3DStyle.RaisedInner), Border3DStyle), Border3DSide.All) Else If (hasicon) Then g.FillRectangle(SystemBrushes.Menu, New Rectangle(bounds.X, bounds.Y, bounds.X + SystemInformation.SmallIconSize.Width + 5, bounds.Height)) bounds.X += SystemInformation.SmallIconSize.Width + 5 bounds.Width -= SystemInformation.SmallIconSize.Width + 5 End If g.FillRectangle(SystemBrushes.Highlight, bounds) End If Else If (toplevel) Then g.FillRectangle(SystemBrushes.Control, bounds) Else g.FillRectangle(SystemBrushes.Menu, bounds) End If End If End Sub Public Sub DrawMenuText(ByVal g As Graphics, ByVal Bounds As Rectangle, ByVal Text As String, ByVal ShortCut As String, ByVal Enabled As Boolean, ByVal TopLevel As Boolean, ByVal State As DrawItemState) Implements MenuItemStyleDrawer.DrawMenuText Dim selected As Boolean = (State And DrawItemState.Selected) > 0 Dim _stringformat As StringFormat = New StringFormat _stringformat.HotkeyPrefix = CType(IIf(((State And DrawItemState.NoAccelerator) > 0), HotkeyPrefix.Hide, HotkeyPrefix.Show), HotkeyPrefix) Dim shortcutwidth As Integer = CType(g.MeasureString(ShortCut, SystemInformation.MenuFont).Width, Integer) Dim textwidth As Integer = CType(g.MeasureString(Text, SystemInformation.MenuFont).Width, Integer) Dim x As Integer = CType(IIf(TopLevel, Bounds.Left + (Bounds.Width - textwidth) / 2, Bounds.Left + TEXTSTART), Integer) Dim y As Integer = Bounds.Top + 2 If (Enabled) Then '// normal draw Dim color As Color = CType(IIf((selected And (Not TopLevel)), color.White, SystemColors.MenuText), Color) g.DrawString(Text, SystemInformation.MenuFont, New SolidBrush(color), x, y, _stringformat) g.DrawString(ShortCut, SystemInformation.MenuFont, New SolidBrush(color), Bounds.Left + 130, Bounds.Top + 2, _stringformat) Else '// disabled menuitem draw If (Not selected) Then g.DrawString(Text, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, x + 1, y + 1, _stringformat) g.DrawString(ShortCut, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, Bounds.Right - shortcutwidth - 10 + 1, Bounds.Top + 2 + 1, _stringformat) End If g.DrawString(Text, SystemInformation.MenuFont, New SolidBrush(SystemColors.GrayText), x, y, _stringformat) g.DrawString(ShortCut, SystemInformation.MenuFont, New SolidBrush(SystemColors.GrayText), Bounds.Right - shortcutwidth - 10, Bounds.Top + 2, _stringformat) End If End Sub End Class Public Class VSNetStyle : Implements MenuItemStyleDrawer ' El color de fondo de los menús Shared bgcolor As Color = SystemColors.ControlLightLight '//Color.FromArgb(246, 246, 246); Dim ibgcolor As Color = SystemColors.Control 'SystemColors.ControlLight ' El color de la banda izquierda de los menús '//Color.FromArgb(202, 202, 202); Shared sbcolor As Color = Color.FromArgb(200, 215, 240) ' color de fondo del elemento seleccionado ' Color.FromArgb(173, 173, 209) Dim sbbcolor As Color = Color.FromArgb(60, 96, 192) ' Color alrededor de la selección '0,0,128 Dim TEXTSTART As Integer = 20 ' Public Shared ReadOnly Property BackColor() As Color Get Return bgcolor End Get End Property Public Shared ReadOnly Property SelectedBackColor() As Color Get Return sbcolor End Get End Property ' Public Sub DrawCheckmark(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal selected As Boolean) Implements MenuItemStyleDrawer.DrawCheckmark ControlPaint.DrawMenuGlyph(g, New Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark) 'g.DrawRectangle(new Pen(sbbcolor), bounds.X + 1, bounds.Y + 1, 14 + 1, 14 + 1); End Sub Public Sub DrawIcon(ByVal g As Graphics, ByVal icon As Image, ByVal bounds As Rectangle, ByVal selected As Boolean, ByVal enabled As Boolean, ByVal ischecked As Boolean) Implements MenuItemStyleDrawer.DrawIcon If (enabled) Then If (selected) Then ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, Color.Black) g.DrawImage(icon, bounds.Left + 1, bounds.Top + 1) Else g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2) End If Else ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.HighlightText) End If End Sub Public Sub DrawSeparator(ByVal g As Graphics, ByVal bounds As Rectangle) Implements MenuItemStyleDrawer.DrawSeparator Dim y As Integer = CType(bounds.Y + bounds.Height / 2, Integer) g.DrawLine(New Pen(SystemColors.ControlDark), bounds.X + SystemInformation.SmallIconSize.Width + 7, y, bounds.X + bounds.Width - 2, y) End Sub Public Sub DrawBackground(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal state As DrawItemState, ByVal toplevel As Boolean, ByVal hasicon As Boolean) Implements MenuItemStyleDrawer.DrawBackground Dim selected As Boolean = (state And DrawItemState.Selected) > 0 If (selected OrElse ((state And DrawItemState.HotLight) > 0)) Then If (toplevel AndAlso selected) Then '// draw toplevel, selected menuitem g.FillRectangle(New SolidBrush(ibgcolor), bounds) ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top Or Border3DSide.Left Or Border3DSide.Right) Else '// draw menuitem, selected OR toplevel, hotlighted g.FillRectangle(New SolidBrush(sbcolor), bounds) g.DrawRectangle(New Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1) End If Else If (Not toplevel) Then '// draw menuitem, unselected g.FillRectangle(New SolidBrush(ibgcolor), bounds) bounds.X += 16 + 5 bounds.Width -= 16 + 5 g.FillRectangle(New SolidBrush(bgcolor), bounds) Else '// draw toplevel, unselected menuitem g.FillRectangle(SystemBrushes.Control, bounds) End If End If End Sub Public Sub DrawMenuText(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal text As String, ByVal shortcut As String, ByVal enabled As Boolean, ByVal toplevel As Boolean, ByVal state As DrawItemState) Implements MenuItemStyleDrawer.DrawMenuText Dim stringformat As StringFormat = New StringFormat stringformat.HotkeyPrefix = CType(IIf(((state And DrawItemState.NoAccelerator) > 0), HotkeyPrefix.Hide, HotkeyPrefix.Show), HotkeyPrefix) Dim textwidth As Integer = CType(g.MeasureString(text, SystemInformation.MenuFont).Width, Integer) Dim shortcutwidth As Integer = CType(g.MeasureString(shortcut, SystemInformation.MenuFont).Width, Integer) Dim x As Integer = CType(IIf(toplevel, bounds.Left + (bounds.Width - textwidth) / 2, bounds.Left + TEXTSTART), Integer) Dim y As Integer = bounds.Top + 2 Dim brush As Brush = Nothing If (Not enabled) Then brush = New SolidBrush(Color.FromArgb(120, SystemColors.MenuText)) Else brush = New SolidBrush(SystemColors.MenuText) End If g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat) g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat) End Sub End Class 'End Namespace
// RichMenuItem.cs // Copyright (c) 2001 Mike Krueger // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Drawing; using System.Diagnostics; using System.Drawing.Text; using System.Drawing.Imaging; using System.Windows.Forms; //using SharpDevelop.Gui.Window; //using SharpDevelop.Tool.Data; //using SharpDevelop.Internal.ExternalTool; //using SharpDevelop.Internal.Text; namespace NCvs.Gui.Components { public enum IconMenuStyle { Standard, Office2000, VSNet }; public interface MenuItemStyleDrawer { void DrawCheckmark(Graphics g, Rectangle bounds, bool selected); void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked); void DrawSeparator(Graphics g, Rectangle bounds); void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon); void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state); } public class Office2000Style : MenuItemStyleDrawer { static int TEXTSTART = 20; public void DrawCheckmark(Graphics g, Rectangle bounds, bool selected) { ControlPaint.DrawMenuGlyph(g, new Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark); } public void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked) { if (enabled) { g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2); } else ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.Control); if (selected) ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, icon.Width + 3, icon.Height + 3, Border3DStyle.RaisedInner); } public void DrawSeparator(Graphics g, Rectangle bounds) { ControlPaint.DrawBorder3D(g, bounds.X, bounds.Y + 2, bounds.Width, 3, Border3DStyle.Etched, Border3DSide.Top); } public void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon) { bool selected = (state & DrawItemState.Selected) > 0; if (selected ||((state & DrawItemState.HotLight) > 0)) { if (toplevel) { // g.FillRectangle(SystemBrushes.Highlight, bounds); ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, selected ? Border3DStyle.SunkenOuter : Border3DStyle.RaisedInner, Border3DSide.All); } else { if (hasicon) { g.FillRectangle(SystemBrushes.Menu, new Rectangle(bounds.X, bounds.Y, bounds.X + SystemInformation.SmallIconSize.Width + 5, bounds.Height)); bounds.X += SystemInformation.SmallIconSize.Width + 5; bounds.Width -= SystemInformation.SmallIconSize.Width + 5; } g.FillRectangle(SystemBrushes.Highlight, bounds); } } else { if (toplevel) { g.FillRectangle(SystemBrushes.Control, bounds); } else { g.FillRectangle(SystemBrushes.Menu, bounds); } } } public void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state) { bool selected = (state & DrawItemState.Selected) > 0; StringFormat stringformat = new StringFormat(); stringformat.HotkeyPrefix = ((state & DrawItemState.NoAccelerator) > 0) ? HotkeyPrefix.Hide : HotkeyPrefix.Show; int shortcutwidth = (int)(g.MeasureString(shortcut, SystemInformation.MenuFont).Width); int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width); int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART; int y = bounds.Top + 2; if (enabled) { // normal draw Color color = (selected && !toplevel) ? Color.White : SystemColors.MenuText; g.DrawString(text, SystemInformation.MenuFont, new SolidBrush(color), x, y, stringformat); g.DrawString(shortcut, SystemInformation.MenuFont, new SolidBrush(color), bounds.Left + 130, bounds.Top + 2, stringformat); } else { // disabled menuitem draw if (!selected) { g.DrawString(text, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, x + 1, y + 1, stringformat); g.DrawString(shortcut, SystemInformation.MenuFont, SystemBrushes.ControlLightLight, bounds.Right - shortcutwidth - 10 + 1, bounds.Top + 2 + 1, stringformat); } g.DrawString(text, SystemInformation.MenuFont, new SolidBrush(SystemColors.GrayText), x, y, stringformat); g.DrawString(shortcut, SystemInformation.MenuFont, new SolidBrush(SystemColors.GrayText), bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat); } } } public class VSNetStyle : MenuItemStyleDrawer { static Color bgcolor = SystemColors.ControlLightLight; //Color.FromArgb(246, 246, 246); static Color ibgcolor = SystemColors.ControlLight; //Color.FromArgb(202, 202, 202); static Color sbcolor = Color.FromArgb(173, 173, 209); static Color sbbcolor = Color.FromArgb( 0, 0, 128); static int TEXTSTART = 20; public void DrawCheckmark(Graphics g, Rectangle bounds, bool selected) { ControlPaint.DrawMenuGlyph(g, new Rectangle(bounds.X + 2, bounds.Y + 2, 14, 14), MenuGlyph.Checkmark); } public void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked) { if (enabled) { if (selected) { ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, Color.Black); g.DrawImage(icon, bounds.Left + 1, bounds.Top + 1); } else { g.DrawImage(icon, bounds.Left + 2, bounds.Top + 2); } } else ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 2, SystemColors.HighlightText); } public void DrawSeparator(Graphics g, Rectangle bounds) { int y = bounds.Y + bounds.Height / 2; g.DrawLine(new Pen(SystemColors.ControlDark), bounds.X + SystemInformation.SmallIconSize.Width + 7, y, bounds.X + bounds.Width - 2, y); } public void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon) { bool selected = (state & DrawItemState.Selected) > 0; if (selected || ((state & DrawItemState.HotLight) > 0)) { if (toplevel && selected) { // draw toplevel, selected menuitem g.FillRectangle(new SolidBrush(ibgcolor), bounds); ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right); } else { // draw menuitem, selected OR toplevel, hotlighted g.FillRectangle(new SolidBrush(sbcolor), bounds); g.DrawRectangle(new Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); } } else { if (!toplevel) { // draw menuitem, unselected g.FillRectangle(new SolidBrush(ibgcolor), bounds); bounds.X += 16 + 5; bounds.Width -= 16 + 5; g.FillRectangle(new SolidBrush(bgcolor), bounds); } else { // draw toplevel, unselected menuitem g.FillRectangle(SystemBrushes.Control, bounds); } } } public 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; int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width); int shortcutwidth = (int)(g.MeasureString(shortcut, SystemInformation.MenuFont).Width); int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART; int y = bounds.Top + 2; Brush brush = null; if (!enabled) brush = new SolidBrush(Color.FromArgb(120, SystemColors.MenuText)); else brush = new SolidBrush(SystemColors.MenuText); g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat); g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Right - shortcutwidth - 10, bounds.Top + 2, stringformat); } } public class RichMenuItem : MenuItem { string shortcuttext = ""; StringFormat stringformat = new StringFormat(); Bitmap icon = null; MenuItemStyleDrawer style = null; IconMenuStyle menustyle = IconMenuStyle.VSNet; int shortcuttextwidth; public IconMenuStyle MenuStyle { get { return menustyle; } set { switch (value) { case IconMenuStyle.Office2000: style = new Office2000Style(); OwnerDraw = true; break; case IconMenuStyle.VSNet: style = new VSNetStyle(); OwnerDraw = true; break; default: style = null; OwnerDraw = false; break; } } } public string ShortcutText { get { return shortcuttext; } set { shortcuttext = value; } } public Bitmap Icon { get { return icon; } set { icon = value; } } public RichMenuItem() { } public RichMenuItem(IconMenuStyle style, string name, EventHandler handler, Shortcut shortcut) : this(style, name, handler) { this.Shortcut = shortcut; } public RichMenuItem(IconMenuStyle style, string name) : base(name) { MenuStyle = style; } public RichMenuItem(IconMenuStyle style, string name, EventHandler handler) : base(name, handler) { MenuStyle = style; } public RichMenuItem(IconMenuStyle style, string name, MenuItem[] items) : base(name, items) { MenuStyle = style; } // public override MenuItem CloneMenu() // { // return (MenuItem)MemberwiseClone(); // } protected override void OnMeasureItem(MeasureItemEventArgs e) { base.OnMeasureItem(e); // make shortcut text 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 text += (char)ch; shortcuttext = text; } if (menustyle != IconMenuStyle.Standard) { if (Text == "-") { e.ItemHeight = 8; e.ItemWidth = 4; return; } int textwidth = (int)(e.Graphics.MeasureString(Text, SystemInformation.MenuFont).Width); shortcuttextwidth = (int)(e.Graphics.MeasureString(shortcuttext, SystemInformation.MenuFont).Width); textwidth += shortcuttextwidth; e.ItemHeight = SystemInformation.MenuHeight; if (Parent == Parent.GetMainMenu()) e.ItemWidth = textwidth - 5; // 5 is a magic number :) else e.ItemWidth = Math.Max(160, textwidth + 15); } } protected override void OnSelect(EventArgs e) { base.OnSelect(e); } protected override void OnDrawItem(DrawItemEventArgs e) { base.OnDrawItem(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; style.DrawBackground(g, bounds, e.State, toplevel, hasicon); if (hasicon) style.DrawIcon(g, Icon, bounds, selected, Enabled, Checked); else if (Checked) style.DrawCheckmark(g, bounds, selected); if (Text == "-") { style.DrawSeparator(g, bounds); } else { style.DrawMenuText(g, bounds, Text, shortcuttext, Enabled, toplevel, e.State); } } } }
La autorización de Mike Krüger para publicar el código traducido a VB.NET sin necesidad de usar el GPL:
Como notarás hace tiempo de esto... y hasta ahora no lo había publicado... en fin cosas de las pocas neuronas que tengo, y si no llega a ser por una pregunta en los grupos de noticias, pues ni me hubiese acordado, ya que tanto en Visual Basic 2005 como Visual C# 2005 se incluye la posibilidad de usar iconos en los menús.
From: "Mike Krüger" <[email protected]>
To: "Guillermo 'guille'" <[email protected]>
Sent: Wednesday, January 16, 2002 6:42 PM
Subject: Re: SharpDevelop
Hi
> And also I want to ask you if I can use the RichMenuItem class, (I
translate it
> to VB.NET and works fine), and I would like to publish a sample code using
that
> class. I have a site dedicated to VB (and soon to C#).
Sorry, I clicked send to fast :(
Yes you can use the RichMenuItem class in a sample without the GPL applied.
(thanx that you ask, I give code away, if people just >ask< :))
cya