简体   繁体   中英

Drawing text in vb.net to match a menu item

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:

具有模糊文本的示例菜单具有模糊文本的示例菜单

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?

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

在此输入图像描述

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

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)

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM