在组合框中显示 True Type 字体图像而不是名称 [英] Show the True Type Font image in Combobox instead of the name
问题描述
@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屋!