在组合框中显示 True Type 字体图像而不是名称 [英] Show the True Type Font image in Combobox instead of the name

查看:17
本文介绍了在组合框中显示 True Type 字体图像而不是名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Plutonix 在此链接上的参考答案

我想我为图像使用了太大的字体,但您明白了.您可以使用小于实际大小的 rect 缩小图像(缩略图),但它可能无法像实际使用较小的字体/图像那样缩放.

Reference answer of @Plutonix on this link 3D array loop and get the first dimension value

The class I'm adapting to show the TTF image on the combobox

Public Class FontItem
    Public Property TTImageFile As Image
    Public Property TTFile As String
    Public Property TTBoldFile As String
    Public Property Name As String
    Public Sub New(i as Image, f As String, b As String, n As String)
        TTImageFile = i
        TTFile = f
        TTBoldFile = b
        Name = n
    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class

Using this code this way

    Dim myFonts As New List(Of FontItem)

    Dim data = {{My.Resources.arial, "Arial", "arial.ttf", "arialbd.ttf"},
        {My.Resources.courier, "Courier New", "cour.ttf", "courbd.ttf"},
        {My.Resources.verdana, "Verdana", "verdana.ttf", "verdanab.ttf"}}

    For n As Int32 = 0 To data.GetUpperBound(0)
        myFonts.Add(New FontItem(data(n, 0), data(n, 1), data(n, 2), data(n, 3)))
    Next

    AvialableFontsCombobox.DataSource = myFonts.ToArray()

Where "My.Resources.arial" and the others are the png file of the font preview

The code works fine but my AvialableFontsCombobox only show "arial.png", "courier.png"... as string instead of the graphic file.

And adding

    With AvialableFontsCombobox 
        .DrawMode = DrawMode.OwnerDrawVariable
    End With

I only get blank spaces.

What I'm missing? Do I need to do something more on??

Private Sub AvialableFontsCombobox _DrawItem(sender As Object, e As DrawItemEventArgs) Handles AvialableFontsCombobox .DrawItem

解决方案

When you set a Combo- or ListBox to OwnerDraw you are saying that you will handle the drawing of the items - that means adding code to the DrawItem event. In this case it appears that you want to draw some PNG images for each. An alternative would be to draw the name of each font (or sample text) in that Font. The image approach is probably easier because you can be sure that each image is exactly the same size even if that means a little more white space on some.

First some setup things:

Turn Option Strict On. You are storing an image from resources along with some strings in one array which means the array is Object. I like the idea of storing all the little pieces together, but there is another concern...

You want to be sure those references to My.Resources.fontname run once only. Every time that code runs it is creating a new image object. If you arent checking and disposing of old ones, your app will leak (The list from a previous question was much longer).

' form/class level declaration
Private FontImgs As Image()

Elsewhere to initialize:

' build it only once
If FontImgs Is Nothing Then
    FontImgs = New Image() {My.Resources.Arial, My.Resources.Calibri,
                            My.Resources.Segoe, My.Resources.Verdana}
End If

Dim myFonts As New List(Of FontItem)

Dim data = {{"Arial", "arial.ttf", "arialbd.ttf"},
           {"Calibri", "Calibri.ttf", "Calibri.ttf"},
           {"Segoe", "Segoe.ttf", "Segoe.ttf"},
           {"Verdana", "verdana.ttf", "verdanab.ttf"}
           }

For n As Int32 = 0 To FontImgs.Length - 1
    myFonts.Add(New FontItem(FontImgs(n), data(n, 1), data(n, 2), data(n, 0)))
Next

cboFonts.DataSource = myFonts
cboFonts.DisplayMember = "Name"

If you initialize the list an array somewhere close to each other, it will be easy to make sure the Image references are in the same order as the rest of the font data. By the way, your code is passing the Name as the FontFile - the order to the constructor seems incorrect.

  • Create the images with a Transparent BG
  • Make them all the same size but only as large as needed for the longest of them (minimize white space)
  • There is no need to add items to the control, just use your list as the DataSource

If this is on a Dialog form that gets re-visited, either be sure to dispose of the images in that array, or make it an app level object that is passed to the form.

For the CBO:

  • OwnerDraw = Fixed
  • ItemHeight = Height of the images. Mine are all 179w x 28h, so I used 28
  • DropDownHeight to some multiple of the image height plus a margin. Example: 95 allows 3 images to show before the scroll bar appears.
  • DropDownWidth to accommodate the image width plus a bit; I used 190
  • The Text portion of the control will follow the item size to allow you to draw the selected Item there. I am letting it print the "Name" (`DisplayMember') there but I set the font size to 14 make use of the space

Once it is set up, add some code to the DrawItem event:

Private Sub cboFonts_DrawItem(sender As Object, 
            e As DrawItemEventArgs) Handles cboFonts.DrawItem

    ' no item, early exit
    If e.Index < 0 Then Return

    e.DrawBackground()
    ' get the image from the cbo.fiontitem.imageprop
    Dim img = DirectCast(cboFonts.Items(e.Index), FontItem).TTImageFile

    ' size of the image
    Dim rect = New Rectangle(e.Bounds.X, e.Bounds.Y,
                                img.Width, img.Height)
    ' draw it
    e.Graphics.DrawImage(img, rect)

    e.DrawFocusRectangle()

End Sub

I think I used a too large Font for the images, but you get the idea. You can shrink the images a little by using a rect smaller than the actual size (thumbnailing them), but it may not scale as well as actually using a smaller font/image.

这篇关于在组合框中显示 True Type 字体图像而不是名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆