Reputation: 45
So I've searched around and managed to highlight the values in my ListBox
, but I'm trying to increase the font size for the text inside the ListBox
but it results in the following image as attached:
This is my current code:
Private Sub ListBox1_DrawItem(sender As System.Object, e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
e.DrawBackground()
If ListBox1.Items(e.Index).ToString().Contains("*") Then
e.Graphics.FillRectangle(Brushes.Red, e.Bounds)
End If
e.Graphics.DrawString(ListBox1.Items(e.Index), e.Font, Brushes.Black, New System.Drawing.PointF(e.Bounds.X, e.Bounds.Y))
e.DrawFocusRectangle()
I've tried messing with the "e.Bounds.X, e.Bounds.Y" to increase the rectangle/size of the highlighted value but nothing seemed to work.
How does one allow the highlighted rectangle increase according to the font size?
Upvotes: 2
Views: 935
Reputation: 32248
When you set the DrawMode of a ListBox
control to OwnerDrawVariable or you change the Font size after the control handle has been created (i.e. after it has already processed the WM_MEASUREITEM
message), you need to manually set the ItemHeigh property to the new Font height.
The ItemHeight
property is set subscribing the ListBox
MeasureItem event and setting the MeasureItemEventArgs
e.ItemHeight
property.
Also, if you change the Font size on the fly, you also need to force the WM_MEASUREITEM
message to be re-sent to the ListBox
control, otherwise the Items Bounds will not be updated.
In other words, when the DrawItem
event is raised, the DrawItemEventArgs
e.Bounds
property will report wrong measures.
A way to force the ListBox
control to re-measure its Items bounds, is to set ListBox.DrawMode = DrawMode.Normal
and immediatly resetting it back to OwnerDrawVariable
. This causes the WM_MEASUREITEM
message to be processed again.
listBox1.DrawMode = DrawMode.Normal
listBox1.DrawMode = DrawMode.OwnerDrawVariable
listBox1.Update()
Here I'm using the Font.Height
to measure the current ItemHeight
in the MeasureItem
event, because it rounds up the measure. You could use TextRenderer.MeasureText or Font.GetHeight(); you'll end up with the same measure, but rounded down.
Private Sub ListBox1_DrawItem(sender As Object, e As DrawItemEventArgs) Handles ListBox1.DrawItem
Dim ItemForeColor As Color
Dim ItemBackColor As Color
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
ItemForeColor = Color.FromKnownColor(KnownColor.HighlightText)
ItemBackColor = If(ListBox1.Items(e.Index).ToString().Contains("*"), Color.Red, Color.FromKnownColor(KnownColor.Highlight))
Else
ItemForeColor = ListBox1.ForeColor
ItemBackColor = If(ListBox1.Items(e.Index).ToString().Contains("*"), Color.Red, ListBox1.BackColor)
End If
Using TextBrush As New SolidBrush(ItemForeColor)
Using ItemBrush As New SolidBrush(ItemBackColor)
e.Graphics.FillRectangle(ItemBrush, e.Bounds)
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), ListBox1.Font, TextBrush, e.Bounds, StringFormat.GenericTypographic)
End Using
End Using
e.DrawFocusRectangle()
End Sub
Private Sub ListBox1_MeasureItem(sender As Object, e As MeasureItemEventArgs) Handles ListBox1.MeasureItem
e.ItemHeight = ListBox1.Font.Height
End Sub
Test it resizing the Font:
ListBox1.Font = New Font(ListBox1.Font.FontFamily, ListBox1.Font.SizeInPoints + 2, ListBox1.Font.Style, GraphicsUnit.Point)
ListBox1.DrawMode = DrawMode.Normal
ListBox1.DrawMode = DrawMode.OwnerDrawVariable
ListBox1.Height = '[OriginalHeight]
ListBox1.Update()
Upvotes: 2