menu strip question

Anti-Rich

Well-known member
Joined
Jul 1, 2006
Messages
325
Location
Perth, Australia
Programming Experience
1-3
hi all,

i have recently discovered how to use gradients in my application, and i am pretty happy with the results. at the moment i have a dark blue - light blue fade and it looks good :)

with my menu strip, i feel that the edges of the menu are too sharp, and detract from the 'shiny' or 'smooth' look of the application. so my question is, how can i round off the edges of the menu itself ..

i have attached a picture showing what i mean...

cheers all
adam
 

Attachments

  • sample3.JPG
    sample3.JPG
    10.9 KB · Views: 74
You could perhaps draw an artistic arc in lower-right corner, this can be done in OnRenderToolStripBorder. Example image attached where drawn with SystemColors.ControlDark, same as the shadow.
 

Attachments

  • arc-sample3.JPG
    arc-sample3.JPG
    6.9 KB · Views: 71
You can also adjust the shape of the window if you like, but you will need to be able to get the hWnd (window handle) of the dropdown menu. I haven't worked out how to do that yet but when I do i'll get back to you.
 
Good idea vis781, I didn't find the connection of the object to change shape for right away, here it is:
VB.NET:
    Class renderer
        Inherits ToolStripSystemRenderer
 
        Protected Overrides Sub OnRenderToolStripBorder(ByVal e As System.Windows.Forms.ToolStripRenderEventArgs)
            MyBase.OnRenderToolStripBorder(e)
            If e.ToolStrip.IsDropDown Then
                e.ToolStrip.Region = New Region(RoundRect(e.AffectedBounds, 30))
            End If
        End Sub
 
        Public Function RoundRect(ByVal rct As Rectangle, ByVal radius As Integer) _
        As Drawing2D.GraphicsPath
            Dim gp As New Drawing2D.GraphicsPath
            [COLOR=darkgreen]'top line[/COLOR]
            gp.AddLine(rct.Left, rct.Top, rct.Right, rct.Top)
            [COLOR=darkgreen]'top right arc[/COLOR]
            'gp.AddArc(rct.X + rct.Width - radius, rct.Y, radius, radius, 270, 90)
            [COLOR=darkgreen]'bottom right arc[/COLOR]
            gp.AddArc(rct.X + rct.Width - radius, rct.Y + rct.Height - radius, radius, radius, 0, 90)
            [COLOR=darkgreen]'bottom left arc[/COLOR]
            gp.AddArc(rct.X, rct.Y + rct.Height - radius, radius, radius, 90, 90)
            [COLOR=darkgreen]'top left arc[/COLOR]
            'gp.AddArc(rct.X, rct.Y, radius, radius, 180, 90)
            gp.CloseFigure()
            Return gp
        End Function
 
    End Class
All four corners are included, but commented out the top and added a line there to only round bottom corners.
If you only want to round bottom right corner you must add the point of the bottom left corner in the graphicspath lines.
 
Anti-Rich, since you asked specifically only to round bottom right corner, here is the function that returns such a graphicspath:
VB.NET:
Public Function RoundRectBR(ByVal rct As Rectangle, ByVal radius As Integer) As Drawing2D.GraphicsPath
    Dim gp As New Drawing2D.GraphicsPath
[COLOR=darkgreen]    'point tl,tr,bl[/COLOR]
    Dim pts(2) As Point
    pts(0) = New Point(rct.Left, rct.Bottom)
    pts(1) = New Point(rct.Left, rct.Top)
    pts(2) = New Point(rct.Right, rct.Top)
    gp.AddLines(pts)
[COLOR=darkgreen]    'bottom right arc[/COLOR]
    Dim br As New Rectangle(rct.Right - radius, rct.Bottom - radius, radius, radius)
    gp.AddArc(br, 0, 90)
    gp.CloseFigure()
    Return gp
End Function
 
cheers guys your a bloody lifesaver!!! i would have had no idea at all of how to do that, and now that i know that i can adapt it to future things! :) god bless these forums :p

have a good one :)
adam
 
Corner rounding can be useful for many different things, I was getting a bit annoyed at trying out the different cornering 'manually' so I rewrote the rounding method to allow easy selection of which corners to round, using only a flags enumeration to choose, here it is if you want to try these same:
VB.NET:
[SIZE=2]<Flags()> [/SIZE]Public Enum corners
    none = 0
    topleft = 1
    topright = 2
    bottomleft = 4
    bottomright = 8
[SIZE=2]    all = topleft + topright + bottomleft + bottomright
[/SIZE]End Enum
method, adds up lines/arcs around the rectangle:
VB.NET:
Public Function roundedRect(ByVal rct As Rectangle, ByVal radius As Integer, ByVal corners As corners) As Drawing2D.GraphicsPath
    Dim gp As New Drawing2D.GraphicsPath
    If (corners And corners.topleft) = corners.topleft Then
        gp.AddArc(rct.X, rct.Y, radius, radius, 180, 90)
    Else
        gp.AddLine(New PointF(rct.Left, rct.Top), New PointF(rct.Left + 1, rct.Top))
    End If
    If (corners And corners.topright) = corners.topright Then
        gp.AddArc(rct.X + rct.Width - radius, rct.Y, radius, radius, 270, 90)
    Else
        gp.AddLine(gp.GetLastPoint, New Point(rct.Right, rct.Top))
    End If
    If (corners And corners.bottomright) = corners.bottomright Then
        gp.AddArc(rct.X + rct.Width - radius, rct.Y + rct.Height - radius, radius, radius, 0, 90)
    Else
        gp.AddLine(gp.GetLastPoint, New Point(rct.Right, rct.Bottom))
    End If
    If (corners And corners.bottomleft) = corners.bottomleft Then
        gp.AddArc(rct.X, rct.Y + rct.Height - radius, radius, radius, 90, 90)
    Else
        gp.AddLine(gp.GetLastPoint, New Point(rct.Left, rct.Bottom))
    End If
    gp.CloseFigure()
    Return gp
End Function
Actually, I wrote two different versions, this one take the Rectangle as Region and exclude the chosen corners, it also return the Region directly (not GraphicsPath):
VB.NET:
Public Function roundedRect2(ByVal rct As Rectangle, ByVal radius As Integer, ByVal corners As corners) As Region
    Dim r As New Region(rct)
    Dim ArcRect As New RectangleF(rct.Location, New SizeF(radius, radius))
    Dim gp As New Drawing2D.GraphicsPath
    If (corners And corners.topleft) = corners.topleft Then
        gp.AddArc(ArcRect, 180, 90)
        gp.AddLine(gp.GetLastPoint, New PointF(ArcRect.Left, ArcRect.Top))
        gp.CloseFigure()
    End If
    ArcRect.X = rct.Right - radius
    If (corners And corners.topright) = corners.topright Then
        gp.AddArc(ArcRect, 270, 90)
        gp.AddLine(gp.GetLastPoint, New PointF(ArcRect.Right, ArcRect.Top))
        gp.CloseFigure()
    End If
    ArcRect.Y = rct.Bottom - radius
    If (corners And corners.bottomright) = corners.bottomright Then
        gp.AddArc(ArcRect, 0, 90)
        gp.AddLine(gp.GetLastPoint, New PointF(ArcRect.Right, ArcRect.Bottom))
        gp.CloseFigure()
    End If
    ArcRect.X = rct.Left
    If (corners And corners.bottomleft) = corners.bottomleft Then
        gp.AddArc(ArcRect, 90, 90)
        gp.AddLine(gp.GetLastPoint, New PointF(ArcRect.Left, ArcRect.Bottom))
        gp.CloseFigure()
    End If
    r.Exclude(gp)
    Return r
End Function
example usage in this context:
VB.NET:
Dim c As corners = corners.bottomleft Or corners.topright
'e.ToolStrip.Region = New Region(roundedRect(e.AffectedBounds, 30, c))
e.ToolStrip.Region = roundedRect2(e.AffectedBounds, 30, c)
 
Just for fun here is another one. That takes a rectangle, and returns a region to exclude for rounded corners...

VB.NET:
Friend Function GetTransparentRegion(ByVal Rect As Rectangle) As Region
      Dim UNRctRight As Rectangle
      Dim UNRctBottom As Rectangle
 
 
      Dim FullSize As New Rectangle(Point.Empty, Rect.Size)
      Dim TopLeft As Point = Point.Empty
      Dim TopRight As New Point((FullSize.Width - 1), 0)
      Dim BottomLeft As New Point(0, (FullSize.Height - 1))
      Dim BottomRight As New Point((FullSize.Width - 1), (FullSize.Height - 1))
      Dim TlEftRct As New Rectangle(TopLeft, New Size(1,1))
      Dim BLeftRct As New Rectangle(BottomLeft, New Size(2, 1))
      Dim BrightRct As New Rectangle(BottomLeft.X, (BottomLeft.Y - 1), 1, 2)
      Dim TRightRct As New Rectangle((BottomRight.X - 1), BottomRight.Y, 2, 1)
      Dim UNRctLeft As New Rectangle(BottomRight.X, (BottomRight.Y - 1), 1, 2)
 
     UNRctRight = New Rectangle((TopRight.X - 2), TopRight.Y, 2, 1)
      UNRctBottom = New Rectangle(TopRight.X, TopRight.Y, 1, 3)
 
      Dim TransparentRegion As New Region(TLeftRct)
      TransparentRegion.Union(TLeftRct)
    TransparentRegion.Union(BLeftRct)
      TransparentRegion.Union(BrightRct)
      TransparentRegion.Union(TrightRct)
      TransparentRegion.Union(UNRctLeft)
     TransparentRegion.Union(UNRctRight)
   TransparentRegion.Union(UNRctBottom)
      Return TransparentRegion
End Function


To use..

VB.NET:
Dim TransReg as Region = GetTransparentRegion(Some Rectangle)
 
Graphics.ExcludeClip(TransReg)
 
Back
Top