Question

I'd like to put a number in the left-hand margin of a menu item in vb.net 2010, but it seems this can only be set to an image. So, I've been trying to create an image with the number I want there using Graphics.DrawString(). I've tried various ways, but I can't get the resulting image to look like the text in the menu item itself - is there a way to do this? Here's my current code (allocating an image to measure the text, then reallocating at the correct size is about version 3 of this - pretty ugly, but I'm not sure how else to measure).

mnuItem = New ToolStripMenuItem
numPeople = CInt(Math.Ceiling(Rnd() * 20))

' Calculate the size of the text
qImg = New Bitmap(1, 1)
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
gr = Graphics.FromImage(qImg)
gr.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
sz = gr.MeasureString(numPeople, mnuItem.Font, New Point(0, 0), sf)
w = CInt(Math.Ceiling(sz.Width))
h = CInt(Math.Ceiling(sz.Height))
m = Math.Max(w, h)

' Now allocate an image of the correct size
qImg = New Bitmap(m, m)
gr = Graphics.FromImage(qImg)
gr.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
gr.DrawString(numPeople, mnuItem.Font, Brushes.Black, New RectangleF((m - w) / 2, (m - h) / 2, w, h), sf)

mnuItem.Image = qImg

Here's a couple of examples of what this gives - note how fuzzy the margin text (image) is compared to the menu item text:

Example menu with fuzzy text Example menu with fuzzy text

I've tried all the TextRenderingHint options, and some are better than others, but none give the crisp look of the menu text. Is there a way to get closer to that look?

Was it helpful?

Solution

Have you tried with creating your own ToolStripMenuItem?

Class CustomToolStripMenuItem
    Inherits System.Windows.Forms.ToolStripMenuItem
    Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        e.Graphics.DrawString("11", Me.Font, System.Drawing.Brushes.Black, New System.Drawing.PointF(0, 0))
    End Sub
End Class

I am NOT doing any calculation to correctly display it, but I think you can do it. It appears like this on my system (see the "Save As" item)

enter image description here

OTHER TIPS

This had me stumped for a while and I conclude that this is a bug because as soon as you add a background colour the text displays as you would wish.

I have a solution for you. It uses a gradient brush derived from the Professional Colors class to draw a rectangle in the background of the bitmap before drawing the text.

Dim mnuItem = TestToolStripMenuItem
Dim numPeople = CInt(Math.Ceiling(Rnd() * 20))

Dim qImg = New Bitmap(mnuItem.Height, mnuItem.Height)
Using gr = Graphics.FromImage(qImg)
    Dim sz = gr.MeasureString(numPeople, mnuItem.Font)

    Dim w = CInt(Math.Ceiling(sz.Width))
    Dim h = CInt(Math.Ceiling(sz.Height))

    Dim linGrBrush As New LinearGradientBrush( _
       New Point(0, 0), _
       New Point(qImg.Width, 0), _
       ProfessionalColors.ToolStripGradientBegin, _
       ProfessionalColors.ToolStripGradientEnd)

    gr.FillRectangle(linGrBrush, New Rectangle(0, 0, qImg.Width, qImg.Height))
    gr.DrawString(numPeople, mnuItem.Font, Brushes.Black, New Point((qImg.Width / 2) - (w / 2), (qImg.Height / 2) - (h / 2)))
End Using

mnuItem.Image = qImg

enter image description here

You will need the Imports System.Drawing.Drawing2D line at the top of the class

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top