0

I have a combobox with several customised items. Here's my code (which works perfectly):

Private intcmbFontStyleTotalHeight As Integer
Private CorpusFontStyleTitre1 As Font = New Font(New FontFamily("Lato"), 18, FontStyle.Bold, 3)
Private CorpusFontStyleTitre2 As Font = New Font(New FontFamily("Lato"), 16, FontStyle.Underline Or FontStyle.Bold, 3)
Private CorpusFontStyleTitre3 As Font = New Font(New FontFamily("Lato"), 14, FontStyle.Underline Or FontStyle.Bold, 3)
Private CorpusFontStyleTitre4 As Font = New Font(New FontFamily("Lato"), 12, FontStyle.Underline, 3)
Private CorpusFontStyleCorpsdeTexte As Font = New Font(New FontFamily("Lato"), 12, FontStyle.Regular, 3)
Private FontStyleForDisplay As Font = New Font(New FontFamily("Lato"), 9, FontStyle.Regular, 3)

Public Structure CorpusFontStyleItem
        Dim strTextStyleName As String
        Dim fontTextStyle As Font
        Public Overrides Function ToString() As String
            Return strTextStyleName
        End Function
End Structure

Private Sub frmCorpusManagement_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        LoadcmbFontStyle()
        cmbFontStyle.ComboBox.DrawMode = DrawMode.OwnerDrawVariable
        AddHandler cmbFontStyle.ComboBox.DrawItem, AddressOf cmbFontStyle_DrawItem
        AddHandler cmbFontStyle.ComboBox.MeasureItem, AddressOf cmbFontStyle_MeasureItem
End Sub

Private Sub cmbFontStyle_MeasureItem(ByVal sender As Object, ByVal e As MeasureItemEventArgs)
        Select Case e.Index
            Case "1"
                e.ItemHeight = 50
            Case "2"
                e.ItemHeight = 40
            Case "3"
                e.ItemHeight = 30
            Case "4"
                e.ItemHeight = 20
            Case "5"
                e.ItemHeight = 10
        End Select
        cmbFontStyle.DropDownHeight = intcmbFontStyleTotalHeight

End Sub

Private Sub cmbFontStyle_DrawItem(ByVal sender As Object, ByVal e As DrawItemEventArgs)
        e.DrawBackground()
        Dim myItem As CorpusFontStyleItem = DirectCast(cmbFontStyle.Items(e.Index), CorpusFontStyleItem)
        e.Graphics.DrawString(myItem.strTextStyleName, myItem.fontTextStyle, New SolidBrush(Color.Black), e.Bounds)
        e.DrawFocusRectangle()
End Sub  

Private Sub LoadcmbFontStyle()

        Dim itemCorpusFontStyleTitre1 As New CorpusFontStyleItem With {.strTextStyleName = "Titre 1", .fontTextStyle = CorpusFontStyleTitre1}
        Dim itemCorpusFontStyleTitre2 As New CorpusFontStyleItem With {.strTextStyleName = "Titre 2", .fontTextStyle = CorpusFontStyleTitre2}
        Dim itemCorpusFontStyleTitre3 As New CorpusFontStyleItem With {.strTextStyleName = "Titre 3", .fontTextStyle = CorpusFontStyleTitre3}
        Dim itemCorpusFontStyleTitre4 As New CorpusFontStyleItem With {.strTextStyleName = "Titre 4", .fontTextStyle = CorpusFontStyleTitre4}
        Dim itemCorpusFontStyleCorps As New CorpusFontStyleItem With {.strTextStyleName = "Corps de Texte", .fontTextStyle = CorpusFontStyleCorpsdeTexte}

        cmbFontStyle.Items.Add(itemCorpusFontStyleTitre1)
        cmbFontStyle.Items.Add(itemCorpusFontStyleTitre2)
        cmbFontStyle.Items.Add(itemCorpusFontStyleTitre3)
        cmbFontStyle.Items.Add(itemCorpusFontStyleTitre4)
        cmbFontStyle.Items.Add(itemCorpusFontStyleCorps)

End Sub

Now, I need that the selected item displays using FontStyleForDisplay (same feature as the font combobox in Word).

I guessed it would be achieved with SelectedIndexChanged event and tried this but doesn't seem to work:

Private Sub cmbFontStyle_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbFontStyle.SelectedIndexChanged
        cmbFontStyle.SelectedItem.Graphics.DrawString(cmbFontStyle.Text, FontStyleForDisplay, New SolidBrush(Color.Black), cmbFontStyle.SelectedItem.Bounds)
        cmbFontStyle.SelectedItem.DrawFocusRectangle()
End Sub

I found some answers for wpf but not for Winforms

8oris
  • 320
  • 2
  • 12
  • What are this: `cmbFontStyle.SelectedItem.Graphics.DrawString` and this: `cmbFontStyle.SelectedItem.DrawFocusRectangle()`? `SelectedItem` is a `CorpusFontStyleItem` struct (you should use a Class, not a Structure), it doesn't expose graphics methods. If you want to draw Items with different Fonts, you need to redefine the current Item's Font using the information returned by `[SelectedItem].fontTextStyle` -- See the ComboBox example here: [Properly draw text using GraphicsPath](https://stackoverflow.com/a/53074638/7444103) (last two snippets and the animation). – Jimi Dec 01 '21 at 12:25
  • I check your example (great one by the way) but i don't get how the selected item font is set. Maybe here: `private void cboFontFamily_SelectionChangeCommitted(object sender, EventArgs e) { fontObject.FontFamily = new FontFamily(cboFontFamily.GetItemText(cboFontFamily.SelectedItem)); Canvas.Invalidate(); }` I'm pretty lost. – 8oris Dec 01 '21 at 14:52
  • The ComboBox in the example is filled with FontFamily names. So a `SelectedItem` is a string that contains a FontFamily name, which is used to create a Font using other selected values (Size, Style, Color etc.). A `SelectedItem` in your ComboBox is a `CorpusFontStyleItem` struct. So, when a new selection is made, you need to cast `SelectedItem` to this struct (as mentioned, it should be a Class, not a Structure). The Font is then `DirectCast(SelectedItem, CorpusFontStyleItem).fontTextStyle`. Draw the Item's Text using this Font. – Jimi Dec 01 '21 at 18:34
  • 1
    I suppose you're using a Custom Control derived from ComboBox with `DrawMode` set to `OwnerDrawVariable`. If it's not, then it should be. – Jimi Dec 01 '21 at 18:37
  • Yep, it is, take a look on my code. – 8oris Dec 13 '21 at 13:24

1 Answers1

0

The only way to solve my problem was to set the droplistmode of the combobox to DropDown instead of DropDownList.

8oris
  • 320
  • 2
  • 12