我只用了一个 VB.Net 单元测试,没有 WIN32 API 调用。它包括检查特定字符 U+2026(省略号)和 U+2409(HTab)的代码,还返回具有字形的字符数(以及低值和高值)。我只对等宽字体感兴趣,但很容易改变......
Dim fnt As System.Drawing.Font, size_M As Drawing.Size, size_i As Drawing.Size, size_HTab As Drawing.Size, isMonospace As Boolean
Dim ifc = New Drawing.Text.InstalledFontCollection
Dim bm As Drawing.Bitmap = New Drawing.Bitmap(640, 64), gr = Drawing.Graphics.FromImage(bm)
Dim tf As Windows.Media.Typeface, gtf As Windows.Media.GlyphTypeface = Nothing, ok As Boolean, gtfName = ""
For Each item In ifc.Families
'TestContext_WriteTimedLine($"N={item.Name}.")
fnt = New Drawing.Font(item.Name, 24.0)
Assert.IsNotNull(fnt)
tf = New Windows.Media.Typeface(item.Name)
Assert.IsNotNull(tf, $"item.Name={item.Name}")
size_M = System.Windows.Forms.TextRenderer.MeasureText("M", fnt)
size_i = System.Windows.Forms.TextRenderer.MeasureText("i", fnt)
size_HTab = System.Windows.Forms.TextRenderer.MeasureText(ChrW(&H2409), fnt)
isMonospace = size_M.Width = size_i.Width
Assert.AreEqual(size_M.Height, size_i.Height, $"fnt={fnt.Name}")
If isMonospace Then
gtfName = "-"
ok = tf.TryGetGlyphTypeface(gtf)
If ok Then
Assert.AreEqual(True, ok, $"item.Name={item.Name}")
Assert.IsNotNull(gtf, $"item.Name={item.Name}")
gtfName = $"{gtf.FamilyNames(Globalization.CultureInfo.CurrentUICulture)}"
Assert.AreEqual(True, gtf.CharacterToGlyphMap().ContainsKey(AscW("M")), $"item.Name={item.Name}")
Assert.AreEqual(True, gtf.CharacterToGlyphMap().ContainsKey(AscW("i")), $"item.Name={item.Name}")
Dim t = 0, nMin = &HFFFF, nMax = 0
For n = 0 To &HFFFF
If gtf.CharacterToGlyphMap().ContainsKey(n) Then
If n < nMin Then nMin = n
If n > nMax Then nMax = n
t += 1
End If
Next
gtfName &= $",[x{nMin:X}-x{nMax:X}]#{t}"
ok = gtf.CharacterToGlyphMap().ContainsKey(AscW(ChrW(&H2409)))
If ok Then
gtfName &= ",U+2409"
End If
ok = gtf.CharacterToGlyphMap().ContainsKey(AscW(ChrW(&H2026)))
If ok Then
gtfName &= ",U+2026"
End If
End If
Debug.WriteLine($"{IIf(isMonospace, "*M*", "")} N={fnt.Name}, gtf={gtfName}.")
gr.Clear(Drawing.Color.White)
gr.DrawString($"Mi{ChrW(&H2409)} {fnt.Name}", fnt, New Drawing.SolidBrush(Drawing.Color.Black), 10, 10)
bm.Save($"{fnt.Name}_MiHT.bmp")
End If
Next
输出是
M N=Consolas,gtf=Consolas,[x0-xFFFC]#2488,U+2026。
M N=Courier New, gtf=Courier New,[x20-xFFFC]#3177,U+2026。
M N=Lucida 控制台,gtf=Lucida 控制台,[x20-xFB02]#644,U+2026。
M N=Lucida Sans 打字机,gtf=Lucida Sans 打字机,[x20-xF002]#240,U+2026。
M N=MingLiU-ExtB,gtf=MingLiU-ExtB,[x0-x2122]#212。
M N=MingLiU_HKSCS-ExtB,gtf=MingLiU_HKSCS-ExtB,[x0-x2122]#212。
M N=MS 哥特式,gtf=MS 哥特式,[x0-xFFEE]#15760,U+2026。
M N=NSimSun,gtf=NSimSun,[x20-xFFE5]#28737,U+2026。
M N=OCR A 扩展,gtf=OCR A 扩展,[x20-xF003]#248,U+2026。
M N=SimSun,gtf=SimSun,[x20-xFFE5]#28737,U+2026。
M N=SimSun-ExtB,gtf=SimSun-ExtB,[x20-x7F]#96。
M N=Webdings,gtf=Webdings,[x20-xF0FF]#446。