08-22-2013 08:30 AM
Hi,
I have no problem adding my own menu item to any given context menu, however, it does not suit the look and feel of act! (see picture)
Any ideas?
^ Test is my inserted item.. looking really non-act!-ish
08-26-2013 12:17 AM - edited 08-26-2013 12:33 AM
I ran into a similar problem this week and after searching for a while, I had to end up writing my own DrawMenu and MeasureMenu methods if I wanted the menu options looking like Act.
Basically, right now, your menu is being drawn by windows, and it doesn't know the custom desgin code Act uses (the icon area in gray, rest is white background, blue highlight border etc etc)
You need to set the OwnerDraw property of the menu item to true, and add eventhandlers to the DrawItem and MeasureItem.
Here's the code that helped me quite a bit with drawing: http://www.codeproject.com/Articles/4332/Putting-Images-Next-To-MenuItems-In-A-Menu-in-C
I still have to mess around with mine but it looks close enough at the moment.
08-26-2013 05:34 AM
Here are two classes you can use to mimic the act! menu style. One is for an icon menu item and the second is for a seperator menu item
Usage Example:
Friend Shared WithEvents GroupTreeViewMenu As System.Windows.Forms.MenuItem
GroupTreeViewMenu = New IconMenuItem("Group Tree", CType(GetEmbeddedIcon("TreeView16.ico"), Icon), New EventHandler(AddressOf OnMenuItemClick), Nothing)
Public Class IconMenuItem : Inherits System.Windows.Forms.MenuItem Private m_Icon As Icon Private m_Font As Font Private m_Checked As Boolean Public Sub New(ByVal text As String, ByVal icon As Icon, ByVal onClick As EventHandler, ByVal shortcut As Windows.Forms.Shortcut) MyBase.New(text, onClick, shortcut) OwnerDraw = True m_Font = New Font("Microsoft Sans Serif", 8) m_Checked = False m_Icon = icon End Sub Public Overloads Sub Dispose() m_Font.Dispose() m_Font = Nothing m_Icon.Dispose() m_Icon = Nothing MyBase.Dispose() End Sub Public Property Icon() As Icon Get Return m_Icon End Get Set(ByVal value As Icon) m_Icon = value End Set End Property Public Property isChecked() As Boolean Get Return MyBase.Checked End Get Set(ByVal value As Boolean) MyBase.Checked = value End Set End Property Protected Overrides Sub OnMeasureItem(ByVal e As Windows.Forms.MeasureItemEventArgs) Dim sf As StringFormat = New StringFormat sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show sf.SetTabStops(60, New Single() {0}) MyBase.OnMeasureItem(e) e.ItemHeight = 22 e.ItemWidth = CInt(e.Graphics.MeasureString(GetRealText(), m_Font, 10000, sf).Width) + 10 sf.Dispose() sf = Nothing End Sub Private Function AppendShortcut() As String 'Basicaly determines to draw the HeldButtton+AnyKey thing. Dim sTemp As String sTemp = Me.Text If Me.ShowShortcut And Me.Shortcut <> Windows.Forms.Shortcut.None Then Dim kKeys As Windows.Forms.Keys = CType(Shortcut, Windows.Forms.Keys) sTemp = sTemp & Convert.ToChar(9) & System.ComponentModel.TypeDescriptor.GetConverter(GetType(Windows.Forms.Keys)).ConvertToString(kKeys) End If Return sTemp End Function Protected Overrides Sub OnDrawItem(ByVal e As Windows.Forms.DrawItemEventArgs) Try MyBase.OnDrawItem(e) Dim br As Brush Dim fDisposeBrush As Boolean If CBool(e.State And Windows.Forms.DrawItemState.Selected) Then ' Highlighted / Mouse Hover ' Left Rectangle Dim rcLeft As Rectangle = e.Bounds rcLeft.Width = 24 ' Right Rectangle Dim rcBk As Rectangle = e.Bounds ' Draw the rectangle around the menu border Dim rcBorder As Rectangle = e.Bounds rcBorder.Y += 3 rcBorder.Width -= 2 rcBorder.Height -= 4 'br = New Drawing2D.LinearGradientBrush(rcBorder, SystemColors.Highlight, SystemColors.Control, 0) fDisposeBrush = True ' Blue-ish Color for the highlight br = New SolidBrush(Color.FromArgb(100, 122, 150, 222)) ' Draw the border e.Graphics.FillRectangle(br, rcBorder) ' Draw the highlighted menu e.Graphics.DrawRectangle(New Pen(New SolidBrush(Color.FromArgb(0, 0, 255))), rcBorder) If isChecked Then e.Graphics.DrawIcon(CType(GetEmbeddedIcon("MenuChecked.ico"), Icon), e.Bounds.Left + 5, e.Bounds.Top + 5) Else ' Box under the icon If Not m_Icon Is Nothing Then e.Graphics.DrawIcon(m_Icon, e.Bounds.Left + 5, e.Bounds.Top + 5) End If End If Else ' NOT highlighted ' Left Rectangle Dim rcLeft As Rectangle = e.Bounds rcLeft.Width = 24 'rcLeft.Y += 1 ' ' Right Rectangle Dim rcBk As Rectangle = e.Bounds rcBk.X += 24 ' Move over 24 pixels 'rcBk.Y += 1 ' ' Box under the icon e.Graphics.FillRectangle(SystemBrushes.Control, rcLeft) If isChecked Then e.Graphics.DrawIcon(CType(GetEmbeddedIcon("MenuChecked.ico"), Icon), e.Bounds.Left + 5, e.Bounds.Top + 5) Else If Not m_Icon Is Nothing Then e.Graphics.DrawIcon(m_Icon, e.Bounds.Left + 5, e.Bounds.Top + 5) End If End If br = SystemBrushes.Menu e.Graphics.FillRectangle(br, rcBk) End If ' Only Dispose the brush if we created it, ' not if it was retrieved from SystemBrushes If fDisposeBrush Then br.Dispose() br = Nothing ' Draw the text last ( Always black ) Dim sf As StringFormat = New StringFormat sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show sf.SetTabStops(60, New Single() {0}) br = New SolidBrush(Color.Black) e.Graphics.DrawString(GetRealText(), m_Font, br, e.Bounds.Left + 27, e.Bounds.Top + 5, sf) br.Dispose() br = Nothing sf.Dispose() sf = Nothing Catch ex As Exception ' do nothing End Try End Sub Private Function GetRealText() As String Try Dim s As String = Text ' Append shortcut if one is set and it should be visible If ShowShortcut And Shortcut <> Windows.Forms.Shortcut.None Then ' To get a string representation of a Shortcut value, cast ' it into a Keys value and use the KeysConverter class (via TypeDescriptor). Dim k As Windows.Forms.Keys = CType(Shortcut, Windows.Forms.Keys) 's = s & Convert.ToChar(9) & TypeDescriptor.GetConverter(GetType(Windows.Forms.Keys)).ConvertToString(k) End If Return s Catch ex As Exception ' do nothing End Try Return Text End Function Public Shared Function GetEmbeddedIcon(ByVal strName As String) As Icon Dim sAssemblAndResourceName As String = String.Empty sAssemblAndResourceName = System.Reflection.Assembly.GetExecutingAssembly.GetName.Name + "." + strName Return New Icon(System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(sAssemblAndResourceName.Substring(sAssemblAndResourceName.IndexOf(".") + 1))) End Function End Class ' IconMenuItem Public Class SeperatorMenuItem : Inherits System.Windows.Forms.MenuItem Private m_Font As Font Public Sub New(ByVal text As String) MyBase.New("-") OwnerDraw = True m_Font = New Font("Microsoft Sans Serif", 8) End Sub Public Overloads Sub Dispose() m_Font.Dispose() m_Font = Nothing MyBase.Dispose() End Sub Protected Overrides Sub OnMeasureItem(ByVal e As Windows.Forms.MeasureItemEventArgs) Dim sf As StringFormat = New StringFormat sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show sf.SetTabStops(60, New Single() {0}) MyBase.OnMeasureItem(e) e.ItemHeight = 5 e.ItemWidth = CInt(e.Graphics.MeasureString(GetRealText(), m_Font, 10000, sf).Width) + 10 sf.Dispose() sf = Nothing End Sub Private Function AppendShortcut() As String 'Basicaly determines to draw the HeldButtton+AnyKey thing. Dim sTemp As String sTemp = Me.Text If Me.ShowShortcut And Me.Shortcut <> Windows.Forms.Shortcut.None Then Dim kKeys As Windows.Forms.Keys = CType(Shortcut, Windows.Forms.Keys) sTemp = sTemp & Convert.ToChar(9) & System.ComponentModel.TypeDescriptor.GetConverter(GetType(Windows.Forms.Keys)).ConvertToString(kKeys) End If Return sTemp End Function Protected Overrides Sub OnDrawItem(ByVal e As Windows.Forms.DrawItemEventArgs) Try MyBase.OnDrawItem(e) Dim br As Brush Dim fDisposeBrush As Boolean If CBool(e.State And Windows.Forms.DrawItemState.Selected) Then ' Highlighted / Mouse Hover ' Left Rectangle Dim rcLeft As Rectangle = e.Bounds rcLeft.Width = 24 ' Right Rectangle Dim rcBk As Rectangle = e.Bounds ' Draw the rectangle around the menu border Dim rcBorder As Rectangle = e.Bounds rcBorder.Y += 3 rcBorder.Width -= 2 rcBorder.Height -= 4 'br = New Drawing2D.LinearGradientBrush(rcBorder, SystemColors.Highlight, SystemColors.Control, 0) fDisposeBrush = True ' Bluish Color for the highlight br = New SolidBrush(Color.FromArgb(100, 122, 150, 222)) ' Draw the border e.Graphics.FillRectangle(br, rcBorder) ' Drae the highlighted menu e.Graphics.DrawRectangle(New Pen(New SolidBrush(Color.FromArgb(0, 0, 255))), rcBorder) Else ' NOT highlighted ' Left Rectangle Dim rcLeft As Rectangle = e.Bounds rcLeft.Width = 24 ' Right Rectangle Dim rcBk As Rectangle = e.Bounds rcBk.X += 28 ' Move over 28 pixels rcBk.Y += 3 ' Mpve down 3 pixe3ls ' Box under the icon e.Graphics.FillRectangle(SystemBrushes.Control, rcLeft) br = SystemBrushes.Menu 'e.Graphics.FillRectangle(br, rcBk) 'rcBk.Height = 1 e.Graphics.DrawLine(New Pen(New SolidBrush(Color.FromArgb(172, 168, 153))), rcBk.X, rcBk.Y, rcBk.X + rcBk.Width, rcBk.Y) End If ' Only Dispose the brush if we created it, ' not if it was retrieved from SystemBrushes If fDisposeBrush Then br.Dispose() br = Nothing ' Draw the text last ( Always black ) Dim sf As StringFormat = New StringFormat sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show sf.SetTabStops(60, New Single() {0}) br = New SolidBrush(Color.Black) e.Graphics.DrawString(GetRealText(), m_Font, br, e.Bounds.Left + 27, e.Bounds.Top + 5, sf) br.Dispose() br = Nothing sf.Dispose() sf = Nothing Catch ex As Exception ' do nothing End Try End Sub Private Function GetRealText() As String Try Dim s As String = Text ' Append shortcut if one is set and it should be visible If ShowShortcut And Shortcut <> Windows.Forms.Shortcut.None Then ' To get a string representation of a Shortcut value, cast ' it into a Keys value and use the KeysConverter class (via TypeDescriptor). Dim k As Windows.Forms.Keys = CType(Shortcut, Windows.Forms.Keys) 's = s & Convert.ToChar(9) & TypeDescriptor.GetConverter(GetType(Windows.Forms.Keys)).ConvertToString(k) End If Return "____________________" 's Catch ex As Exception ' do nothing End Try Return Text End Function End Class ' SeperatorMenuItem
08-26-2013 03:25 PM
i would have to search some of my code, but im sure that the menus are built with Infragistics controls..
I just imported the reference to Infragistics and with a few lines of code create a menu item, then added it to the menu.. was simple and straight forward.. of course if they stop using Infragistics then the menu items in a newer ACT version might not work, but for all the current versions it works fine