Imports System.Drawing Imports System.Windows.Forms Public Class OwnerMenu 'holds menu items Private _MenuItems As New ArrayList() 'default font Private _Font As Font = SystemInformation.MenuFont 'default text color Private _TextColor As Color = System.Drawing.SystemColors.MenuText 'constants Private Const NORMALITEMHEIGHT As Integer = 20 Private Const SEPITEMHEIGHT As Integer = 12 Private Const EXTRAWIDTH As Integer = 30 Private Const ICONSIZE16 As Integer = 16 'structure to hold menu items Private Structure LocalMenuItem Dim MenuItemNumber As Integer Dim MenuItem As Windows.Forms.MenuItem Dim Icon As System.Drawing.Icon Dim IconRectangle As System.Drawing.Rectangle Dim TextLeft As Integer Dim TextTopPosition As Integer Dim Font As System.Drawing.Font Dim TextColor As System.Drawing.Color Dim Height As Integer Dim Width As Integer Dim IsSeperator As Boolean End Structure Public Sub New() ' End Sub 'various constructors for the class Public Sub New(ByVal Font As System.Drawing.Font) _Font = Font If _Font.Size > 12 Then _Font = New Font(_Font.Name, 12, _Font.Style) End If End Sub Public Sub New(ByVal TextColor As System.Drawing.Color) _TextColor = TextColor End Sub Public Sub New(ByVal Font As System.Drawing.Font, _ ByVal TextColor As System.Drawing.Color) _TextColor = TextColor _Font = Font If _Font.Size > 12 Then _Font = New Font(_Font.Name, 12, _Font.Style) End If End Sub 'various constructors for the add method Public Sub Add(ByVal MenuItem As Windows.Forms.MenuItem, _ ByVal Icon As System.Drawing.Icon, _ ByVal MenuItemNumber As Integer, _ ByVal IsSeperator As Boolean) Me.Add(MenuItem, Icon, MenuItemNumber, IsSeperator, _Font, _TextColor) End Sub Public Sub Add(ByVal MenuItem As Windows.Forms.MenuItem, _ ByVal Icon As System.Drawing.Icon, _ ByVal MenuItemNumber As Integer, _ ByVal IsSeperator As Boolean, _ ByVal Font As System.Drawing.Font) Me.Add(MenuItem, Icon, MenuItemNumber, IsSeperator, Font, _TextColor) End Sub Public Sub Add(ByVal MenuItem As Windows.Forms.MenuItem, _ ByVal Bitmap As System.Drawing.Bitmap, _ ByVal MenuItemNumber As Integer, _ ByVal IsSeperator As Boolean) Dim Icon As Icon Dim intIndexOfImageIWant As Int16 = 1 Icon = System.Drawing.Icon.FromHandle(Bitmap.GetHicon) Me.Add(MenuItem, Icon, MenuItemNumber, IsSeperator, _Font, _TextColor) End Sub Public Sub Add(ByVal MenuItem As Windows.Forms.MenuItem, _ ByVal Icon As System.Drawing.Icon, _ ByVal MenuItemNumber As Integer, _ ByVal IsSeperator As Boolean, _ ByVal Font As System.Drawing.Font, _ ByVal TextColor As System.Drawing.Color) 'hold and save the last top and left position Static LastTopPosition As Integer Static LastLeftPosition As Integer Dim li As New LocalMenuItem() If MenuItemNumber = 0 Then LastLeftPosition = 2 LastTopPosition = 0 Else 'calculate the new top position LastTopPosition = LastTopPosition + IIf(IsSeperator, _ SEPITEMHEIGHT, NORMALITEMHEIGHT) LastLeftPosition = 2 End If Const ICONWIDTH As Integer = ICONSIZE16 Const ICONHEIGHT As Integer = ICONSIZE16 Dim IconRect As Rectangle 'calculate new drawing rectangle for icon If IsSeperator Then IconRect = New Rectangle(LastLeftPosition, LastTopPosition, _ ICONWIDTH, ICONHEIGHT) Else IconRect = New Rectangle(LastLeftPosition, LastTopPosition + 2, _ ICONWIDTH, ICONHEIGHT) End If 'you don't need to set ownerdraw - the class does it for you MenuItem.OwnerDraw = True With li .MenuItemNumber = MenuItemNumber .Font = Font .MenuItem = MenuItem .Icon = Icon .TextLeft = LastLeftPosition + ICONWIDTH .TextTopPosition = LastTopPosition .IconRectangle = IconRect .TextColor = TextColor .IsSeperator = IsSeperator End With _MenuItems.Add(li) 'set the handlers for the menuitems AddHandler MenuItem.DrawItem, AddressOf Me.DrawItemHandler AddHandler MenuItem.MeasureItem, AddressOf Me.MesaureItemHandler End Sub Private Sub DoDraw(ByVal LI As LocalMenuItem, _ ByRef e As System.Windows.Forms.DrawItemEventArgs) e.DrawBackground() Const LastLeftPosition As Integer = 2 Const ICONWIDTH As Integer = ICONSIZE16 Dim ThisMenuItem As MenuItem = LI.MenuItem Dim MenuItemGraphics As Graphics = e.Graphics Dim bBypassString As Boolean 'set size and textpoint for our text Dim SizeF As SizeF = e.Graphics.MeasureString(LI.MenuItem.Text, _Font) Dim TextPoint As PointF = New PointF(LI.TextLeft, _ LI.TextTopPosition + ((NORMALITEMHEIGHT - SizeF.Height) / 2)) Dim RectHeight As Integer = SizeF.Height If Not LI.Icon Is Nothing Then 'draw the icon MenuItemGraphics.DrawIcon(New Icon(LI.Icon, _ ICONSIZE16, ICONSIZE16), LI.IconRectangle) ElseIf LI.IsSeperator Then 'draw the separator MenuItemGraphics.DrawLine(New Pen(LI.TextColor, 1), _ TextPoint.X, TextPoint.Y + 11, _ TextPoint.X + LI.Width + EXTRAWIDTH, TextPoint.Y + 11) bBypassString = True End If If Not bBypassString Then 'bypass string if separator 'draw differently if enabled/dsabled If LI.MenuItem.Enabled Then MenuItemGraphics.DrawString(Replace(LI.MenuItem.Text, "&", ""), _ LI.Font, New SolidBrush(LI.TextColor), TextPoint) Else MenuItemGraphics.DrawString(Replace(LI.MenuItem.Text, "&", ""), _ LI.Font, New SolidBrush(Drawing.SystemColors.GrayText), TextPoint) End If End If End Sub Private Sub DoMeasure(ByVal LI As LocalMenuItem, _ ByRef e As System.Windows.Forms.MeasureItemEventArgs) 'calculate the size of the drawing area Dim ThisMenuItem_Strings As String() = LI.MenuItem.Text.Split(",") Dim TextSize As SizeF = e.Graphics.MeasureString( _ ThisMenuItem_Strings(0).Replace("&", ""), LI.Font) e.ItemWidth = TextSize.Width + EXTRAWIDTH If LI.MenuItem.Text = "-" Then e.ItemHeight = SEPITEMHEIGHT Else e.ItemHeight = NORMALITEMHEIGHT End If LI.Height = e.ItemHeight LI.Width = e.ItemWidth End Sub Public Sub DrawItemHandler(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DrawItemEventArgs) 'look through the items and find out which one we are drawing Dim li As LocalMenuItem For Each li In _MenuItems If li.MenuItem Is sender Then DoDraw(li, e) Exit For End If Next End Sub Public Sub MesaureItemHandler(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MeasureItemEventArgs) 'look through the items and find out which one we are measuring Dim li As LocalMenuItem For Each li In _MenuItems If li.MenuItem Is sender Then DoMeasure(li, e) Exit For End If Next End Sub End Class