文字列のサイズを測定する方法を C# で見つけようとしています。Win32 で文字列を測定する標準的な方法は、GetTextExtent を使用することです。本当の目標は、フォント文字の平均幅と高さを見つけることです。文字の平均幅を求める標準的な方法は、すべてのアルファベット文字の幅を取得し、52 で割ることから始まります。
size = dc.GetTextExtent(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52);
averageWidth = size / 52;
Microsoft には、特定の DPI 設定でのいくつかのフォント サイズの平均文字幅をリストしたページがあり、GetTextExtent への私自身の呼び出しによってそれらを確認しました。
- タホマ 8pt、96dpi: 13x6 ピクセル
- タホマ 9pt、96dpi: 14x7 ピクセル
- Segoe UI 9pt、96dpi : 15x7 ピクセル
今、.NET WinForms で同じ計算を実行したいと考えています。Graphics.MeasureString() を使用して、コードを思いつきます:
public static SizeF GetAvgCharSizeF(Graphics g, Font font)
{
String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
SizeF textSize = g.MeasureString(s, font);
float baseUnitX = (textSize.Width / s.Length);
float baseUnitY = textSize.Height;
return new SizeF(baseUnitX, baseUnitY);
}
残念ながら、値は既知の受け入れられている真の値と一致しません。
- タホマ 8pt、96dpi: 14x6 ピクセル(14.21x6.09 ピクセル)
- タホマ 9pt、96dpi: 16x7 ピクセル(15.98x6.85 ピクセル)
- Segoe UI 9pt、96dpi: 17x7 ピクセル(17.46x6.91 ピクセル)
平均的な文字幅は問題ありませんが、文字の高さが約 13% 大きすぎます。余分な高さは、アセンダーとディセンダーを含むように変更された高さの分類の違いによるものだと思います。測定ストリングが高すぎる場合は、次のように変更してみました。
String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
に
String s = "acemnorsuvwxyz";
弦の高さがそれほど高くないので、測定された高さは短くなるはずです。いいえ、アセンダーとディセンダーを含む文字列のバージョンとまったく同じ高さを返します(ただし、平均幅はわずかに大きくなります)。
これの原因は何ですか? また、GetTextExtent によって返される受け入れられた値と一致するように、テキストの平均高さに対して何ができるか、平均文字高さを取得できますか?
注: 文字の平均高さを取得する標準的な方法は GetTextMetrics を使用することですが、GetTextExtents によって返される高さは同じ値を返します。