10

この投稿で説明されているように、OpenXML 仕様の公式の式を使用して、Excel 列のピクセル幅を計算しようとしています。ただし、この式を適用するには、標準フォントの最大桁幅を知る必要があります。これは、最も広い数字のピクセル幅です。OpenXML 仕様では、説明として次の例が示されています。

例として Calibri フォントを使用すると、11 ポイントのフォント サイズの最大桁幅は 7 ピクセル (96 dpi) です。

Calibri の 11 ポイントの数字を視覚的に調べて、これが正しいことを確認しましたが、実際には 7 ピクセル幅です。そのため、任意のフォント/サイズの最大桁幅を返すメソッドを作成しようとしています。

この質問の推奨事項に従いましたが、期待した結果が得られません。

ここに私のテストコードがあります:

var font = new Font("Calibri", 11.0f, FontStyle.Regular);

for (var i = 0; i < 10; i++)
{
    Debug.WriteLine(TextRenderer.MeasureText(i.ToString(), font));
}

これは、すべての桁の幅が 15 であることを示しています。

何か提案はありますか?

ありがとう、ティム

4

5 に答える 5

5

TextRendererは、期待どおりに常に正確であるとは限りません。

MSDNから:http://msdn.microsoft.com/en-us/library/8wafk2kt.aspx

たとえば、TextRendererのデフォルトの動作では、描画されたテキストの境界矩形にパディングを追加して、オーバーハングしたグリフに対応します。

Graphicsオブジェクトまたはコントロールオブジェクトがありますか?これらを使用している場合は、期待どおりに正確な結果を得ることができます。

http://msdn.microsoft.com/en-us/library/6xe5hazb(VS.80).aspxをご覧ください

于 2009-12-02T14:11:20.540 に答える
5

MeasureTextはパディングを追加します。フォントサイズにほぼ比例してスケーリングされますが、量はかなり予測できません。秘訣は、2つの測定値を差し引いて、パディングを取り除くことです。このコードは非常に幸せな数字を生成しました:

        float size = 5;
        for (int ix = 0; ix < 10; ++ix) {
            var font = new Font("Calibri", size, FontStyle.Regular);
            string txt = new string('0', 100);
            SizeF sz1 = TextRenderer.MeasureText("00", font) - TextRenderer.MeasureText("0", font);
            Console.WriteLine("{0} {1:N3}", size, sz1.Width);
            size += 2;
        }

出力:

5 4.000
7 5.000
9 6.000
11 7.000
13 9.000
15 10.000
17 12.000
19 13.000
21 14.000
23 16.000

それはあなたが探している7ピクセルを取得します。TrueTypeヒンティングに対応する必要があることに注意してください。数字の形状を調整して、メインステムがピクセル境界に収まるようにすることができます。少なくとも1つのピクセルを追加します。

于 2009-12-02T18:14:42.810 に答える
5

まず、これから紹介するコードは恐ろしいハックのように見えますが、解決策として提示するつもりはありません。むしろ、最終的な解決策につながる可能性のある MeasureText の動作についてもう少し明らかになることを願っています。

私はあなたのコードを少し変更しました。2 つのアンダースコア文字の長さを測定しています。次に、for ループの本体で、両側にアンダースコアがある目的の文字を測定し、2 つのアンダースコア文字の長さだけを差し引きます。テスト シナリオでは、7 という結果が得られました。これの主な目的は、MeasureText が文字単位のパディングを考慮しているか、文字列の先頭/末尾のパディングを考慮しているかを判断することでした。どうやら後者のようです。おそらく、これは、あなたが受け取った他のインプットのいくつかと組み合わされて、より洗練されたソリューションにつながるでしょう.

var font = new Font("Calibri", 11.0f, FontStyle.Regular);
int underscoreWidth = TextRenderer.MeasureText("__", font).Width; 
for (var i = 0; i < 10; i++)
   {
      int charWidth = TextRenderer.MeasureText(String.Concat("_", i.ToString(), "_"), font).Width - underscoreWidth;
      Debug.WriteLine(charWidth);
   }
于 2009-12-02T16:26:24.827 に答える
3

テキストの幅を測定することは悪夢になる可能性があります.なぜ彼らがそれをそれほど混乱させたのかわかりません..

テキストの長さを測定する最も正確な方法は次のとおりです。

    protected int _MeasureDisplayStringWidth ( Graphics graphics, string text, Font font )
    {
        if ( text == "" )
            return 0;

        StringFormat format = new StringFormat ( StringFormat.GenericDefault );
        RectangleF rect = new RectangleF ( 0, 0, 1000, 1000 );
        CharacterRange[] ranges = { new CharacterRange ( 0, text.Length ) };
        Region[] regions = new Region[1];

        format.SetMeasurableCharacterRanges ( ranges );
        format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;

        regions = graphics.MeasureCharacterRanges ( text, font, rect, format );
        rect = regions[0].GetBounds ( graphics );

        return (int)( rect.Right );
    }
于 2009-12-02T14:17:25.067 に答える
1

私はそれがあなたが正確に必要としているものであると100%確信していません。

ただし、このMicrosoftページをご覧になることをお勧めします。

于 2009-12-02T14:07:37.210 に答える