ToolStripCombobox nutzen in Word-ähnlichen Programm als Font-Auswahl

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von Mikro Fahrrad.

    ToolStripCombobox nutzen in Word-ähnlichen Programm als Font-Auswahl

    Hallo,

    zuerst einmal: Ich bin neu hier. Wenn ich in der falschen Kategorie gepostet habe, bitte sagen :)

    Also mein Problem ist ganz einfach: Ich möchte wie in Word eine Combobox haben, aus der der Benutzer die Schriftart auswählen kann. Da es aber in der Symbolleiste sein soll, ist es keine normale Combobox, sondern eine ToolStripCombobox.

    Ich habe ein Video gefunden, was die Problemlösung für eine normale Combobox wiederspiegelt.


    Wie muss ich den Code ändern, damit es auch für eine ToolStripComboboy funktioniert?

    VB.NET-Quellcode

    1. Private FontCollection As New System.Drawing.Text.InstalledFontCollection
    2. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    3. tscFont.DrawMode = DrawMode.OwnerDrawFixed
    4. tscFont.ItemHeight = 20
    5. For Each FontFamily In FontCollection.Families
    6. tscFont.Items.Add(FontFamily.Name)
    7. Next
    8. End Sub
    9. Private Sub tscFont_DrawItem(sender As Object, e As DrawItemEventArgs) Handles tscFont.drawItem
    10. Dim fn As New Font(FontCollection.Families(e.Index), 10)
    11. e.DrawBackground()
    12. e.Graphics.DrawString(FontCollection.Families(e.Index).Name, fn, New SolidBrush(tscFont.ForeColor), e.Bounds)
    13. End Sub


    Vielen Dank für die Hilfe!
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^
    Eine ToolstripComboBox bietet kein DrawItem Handle. Also mußt du dies hinzufügen.

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    2. tscFont.DrawMode = DrawMode.OwnerDrawFixed
    3. tscFont.ItemHeight = 20
    4. ' DrawItem Handle erstellen
    5. AddHandler tscFont.ComboBox.DrawItem, AddressOf tscFont_DrawItem
    6. For Each FontFamily In FontCollection.Families
    7. tscFont.Items.Add(FontFamily.Name)
    8. Next
    9. End Sub
    10. Private Sub tscFont_DrawItem(sender As Object, e As DrawItemEventArgs)
    11. Dim fn As New Font(FontCollection.Families(e.Index), 10)
    12. e.DrawBackground()
    13. e.Graphics.DrawString(FontCollection.Families(e.Index).Name, fn, New SolidBrush(tscFont.ForeColor), e.Bounds)
    14. End Sub

    Danke Cane,

    der Code liefert keine Fehler (mal abgesehen von Zeile 3, was so einfach auch nicht möglich zu sein scheint).

    Das Problem ist, wenn ich das Debugge, sehe ich nur "leere Items" in der Combobox. Und wenn ich eins anklicke kommt IndexOutOfRange in Zeile 14.

    Edit: Ich habe DropDownStyle = DropDownList.

    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^
    Bist du sicher dass du eine ToolStripComboBox erstellt hast?
    Denn so wie ich das sehe hast du eine normale ComboBox wegen:

    VB.NET-Quellcode

    1. tscFont.DrawMode = DrawMode.OwnerDrawFixed
    2. tscFont.ItemHeight = 20


    Bei einer ToolStripComboBox müßte das so aussehen

    VB.NET-Quellcode

    1. tscFont.ComboBox.DrawMode = DrawMode.OwnerDrawFixed
    2. tscFont.ComboBox.ItemHeight = 20




    Edit:
    Kleines Beispiel wie ich es nutze:

    VB.NET-Quellcode

    1. Private Sub LoadFonts()
    2. With tscRtf.ComboBox
    3. .DrawMode = DrawMode.OwnerDrawFixed
    4. AddHandler .DrawItem, AddressOf tscRtf_DrawItem
    5. For Each oFont As FontFamily In FontFamily.Families
    6. .Items.Add(oFont.Name)
    7. Next
    8. End With
    9. End Sub
    10. Private Sub tscRtf_DrawItem(ByVal sender As Object, ByVal e As DrawItemEventArgs) ' Selbst erstelltes Handle
    11. End Sub

    Willkommen im Forum. :thumbup:

    Mikro Fahrrad schrieb:

    Wie muss ich den Code ändern
    Da hast Du Dir ja einen absolut niedlichen Fehler ausgesucht. Gewusst wie kann man den isolieren.

    Problem: Es gibt Schriftarten, die nicht als "Normalfont" existieren.
    Wenn Du die Schriftarten im Font der ComboBox darstellst, ist alles ordentlich:

    Stellst Du die Schriftarten in ihrem Font dar, musst Du den nehmen, der da ist. Warum das im Filmchen funktioniert, weiß ich nicht.
    Jedenfalls musst Du alle Möglichkeiten abtesten, dann klappt es auch mit der Nachbarin:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private FontCollection As New System.Drawing.Text.InstalledFontCollection
    3. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
    4. tscFont.DrawMode = DrawMode.OwnerDrawFixed
    5. tscFont.ItemHeight = 20
    6. For Each FontFamily In FontCollection.Families
    7. tscFont.Items.Add(FontFamily.Name)
    8. Next
    9. tscFont.SelectedIndex = 0
    10. End Sub
    11. Private Sub tscFont_DrawItem(sender As Object, e As DrawItemEventArgs) Handles tscFont.DrawItem
    12. Dim fn As Font
    13. Try
    14. fn = New Font(FontCollection.Families(e.Index), 10, FontStyle.Regular, GraphicsUnit.Point)
    15. Catch ex As Exception
    16. Try
    17. fn = New Font(FontCollection.Families(e.Index), 10, FontStyle.Bold, GraphicsUnit.Point)
    18. Catch ex2 As Exception
    19. fn = New Font(FontCollection.Families(e.Index), 10, FontStyle.Italic, GraphicsUnit.Point)
    20. End Try
    21. End Try
    22. e.DrawBackground()
    23. e.Graphics.DrawString(FontCollection.Families(e.Index).Name, fn, New SolidBrush(tscFont.ForeColor), e.Bounds)
    24. End Sub
    25. End Class


    -----
    @Cane Falsche Antwort. Kopiere den Code und setze einen Haltepunkt rein.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Cane:
    Ich habe da nur den Code aus dem Video abgeschrieben.

    @RodFromGermany
    Vielen Dank. Das ist die Lösung! Stimmt, dass "Regular" bei manchen Fonts nicht zur Verfügung steht, war mir schon bekannt. Ist mir allerdings gerade nicht direkt aufgefallen.

    Jetzt nur noch die Schönheitsfrage:
    Wie bekomme ich das für die ToolStripCombobox hin? Oder hat die eine ähnliche Eigenschaft?
    tscFont.ItemHeight = 20

    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^

    Mikro Fahrrad schrieb:

    ToolStripCombobox
    bietet die Property DrawMode nicht an. :/
    Nimm Dir einen ToolStripContainer, in den kannst Du die ComboBox reinziehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany

    Ja ist mir schon klar, dass man bei den Fonts auf verfügbare Styles achten muß.
    War mir aber jetzt am Anfang nicht so wichtig wie dass es bei einer ToolStripComboBox eben ein wenig anders ist, als bei einer normalen ComboBox.
    Hatte das selbe Problem vor längerer Zeit und wie ich oben beschrieben habe gelöst.

    Edit:
    Doch. ToolStripComboBox.ComboBox.DrawMode
    Ein Schönheitsproblem habe ich dann noch.

    Es gibt ziemlich langnamige Schriftarten, z. B. "Copperplate Gothic Bold", welche aufgrund der Breite nicht in einer Zeile angezeigt werden können. Irgendwie werden die fehlenden Wörter (z. B. "Gothic Bold") dann so teilweise auf der nächsten Zeile angezeigt (siehe Bild)

    Wie kann man das fixen, dass es z. B. wie bei MS Word gemacht wird? (Text einfach nach rechts aus dem Bild laufen lassen)
    Bilder
    • Fail.png

      1,93 kB, 217×86, 452 mal angesehen
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^
    @Mikro Fahrrad Da gibt es noch was eleganteres als Exceptions - IsStyleAvailable:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private FontCollection As New System.Drawing.Text.InstalledFontCollection
    3. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
    4. tscFont.DrawMode = DrawMode.OwnerDrawFixed
    5. tscFont.ItemHeight = 20
    6. For Each FontFamily In FontCollection.Families
    7. tscFont.Items.Add(FontFamily.Name)
    8. Next
    9. tscFont.SelectedIndex = 0
    10. End Sub
    11. Private Sub tscFont_DrawItem(sender As Object, e As DrawItemEventArgs) Handles tscFont.DrawItem
    12. Dim family As FontFamily = FontCollection.Families(e.Index)
    13. Dim fn As Font = New Font(family, 10, Me.GetDefaultStyle(family))
    14. e.DrawBackground()
    15. e.Graphics.DrawString(family.Name, fn, New SolidBrush(tscFont.ForeColor), e.Bounds)
    16. End Sub
    17. Private Function GetDefaultStyle(ByVal font As FontFamily) As FontStyle
    18. If font.IsStyleAvailable(FontStyle.Regular) Then
    19. Return FontStyle.Regular
    20. ElseIf font.IsStyleAvailable(FontStyle.Bold) Then
    21. Return FontStyle.Bold
    22. ElseIf font.IsStyleAvailable(FontStyle.Italic) Then
    23. Return FontStyle.Italic
    24. ElseIf font.IsStyleAvailable(FontStyle.Italic Or FontStyle.Bold) Then
    25. Return FontStyle.Italic Or FontStyle.Bold
    26. Else
    27. Throw New NotSupportedException()
    28. End If
    29. End Function
    30. End Class

    Breite
    Du kannst zumindest die Breite des Font-Textes ermitteln und ggf. die ComboBox breiter oder die Schriftart kleiner machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke, Rod.

    Aber am schönsten wäre es doch so:

    Wenn es nicht so geht, muss ich es halt lassen^^
    Bilder
    • So richtig.png

      4,82 kB, 382×197, 106 mal angesehen
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^
    Mach einfach die ComboBox so breit, wie Du es brauchst.
    Und feddich. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hab die Breite schon auf 180, das ist schon zu viel imho. Und es reicht noch lange nicht für alle.
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^

    Mikro Fahrrad schrieb:

    Und es reicht noch lange nicht für alle.
    Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich bin auf anderem Wege über eine mir brauchbare Lösung gestolpert:

    VB.NET-Quellcode

    1. tscFont.ComboBox.ItemHeight = 15 'statt 20^^


    Manchmal habe ich echt ein Brett vorm Kopf.
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^

    Mikro Fahrrad schrieb:

    brauchbare Lösung
    ist das eher nicht.
    ItemHeight = 12, 15, 20 bei automatischer Breitenermittlung:

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nach ein wenig rumspielen erweist sich 18 als die beste Größe. Ab 19 gibt es diesen hässlichen Zeilenumbruch.
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^

    Mikro Fahrrad schrieb:

    diesen hässlichen Zeilenumbruch
    Welchen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    „Was ich gerade mache? Ich reite Hand in Hand mit dem Matthäus-Effekt auf einer Exponentialfunktion.“ ^^
    @Mikro Fahrrad Link aus Post #14:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
    2. ' ...
    3. BreiteAnpassen(Me.tscFont)
    4. End Sub
    5. Private Sub BreiteAnpassen(ByVal Cb As ComboBox)
    6. Dim g As Graphics = Cb.CreateGraphics()
    7. Dim Breite, MaxBreite As Single
    8. For Each Element In Cb.Items
    9. Breite = g.MeasureString(Element.ToString, Cb.Font).Width
    10. If Breite > MaxBreite Then MaxBreite = Breite
    11. Next
    12. Cb.Width = CInt(MaxBreite) + 20
    13. End Sub

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!