3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

.NETで正確に文字列のサイズを計測するのに2度手間がかかる

Posted at

.NETで文字列のサイズを計測するのにはGraphics.MeasureString()を使いますよね?文字列のサイズが知りたいのに、1度適当なサイズのBitmapGraphics.FromImage()してあげないとMeasureString()が使えないという話は置いておいて、ただ単純にMeasureString()をしただけじゃ、文字列のサイズを正確に計測することはできません。どうしても、左揃えなら右側に、右揃えなら左側に謎の空白ができてしまいます

(正確には、はみ出しを抑制するための空白です。ちゃんと意味があります。)

これを回避するために、MeasureString()の第4引数にStringFormat.GenericTypographicを指定してやる必要があります。ですが、第4引数を指定するには、その前にある第3引数、文字列の最大の長さ、を指定する必要があります。

ここで思います、「今から文字列の長さを知りたいのに、なぜ最大の長さを指定する必要があるのだろう」、と。

確かに、文字を詰めて表示するために上限を決めたり、すでにウィンドウサイズが決まっていたりするのであれば、上限の横幅というのを指定しても良いですが、ほとんどの場合、純粋に文字列を描画したときの長さが知りたいはずですし、ウィンドウサイズが一定のアプリであるとも限りません。

ですから、何らかの値を入れてやる必要があります。適当な定数でも、int.MaxValueでも問題はなさそうですが、あまりスマートではありませんよね。


そこで、一番初めに紹介した、「謎の空白を生み出してしまう計測法」を用います。これは、純粋な文字列のサイズではないですが、「正しい文字列のサイズ」よりもちょっと大きいサイズを取得できることは100%、間違いないので、近似値と言えるこの値を使います。

// Fontという名のフィールドがすでにあるとする

// 適当なBitmapを生成
var bitmap = new Bitmap(16, 16);
// 適当なGraphicsを生成
var graphics = Graphics.FromImage(bitmap);
// 謎の空白付きの文字列のサイズを計測。
var graphicsSize = graphics.MeasureString("成就した恋ほど語るに値しないものはない。", Font);
// ちゃんとした文字列のサイズを計測。
var trueGraphicsSize = graphics.MeasureString("成就した恋ほど語るに値しないものはない。", Font, (int)graphicsSize.Width, StringFormat.GenericTypographic);

bitmap.Dispose();
graphics.Dispose();

適当な定数を使うよりも、こっちの方がスマート……な気がします(計算量は増えるけど)。

謎の空白を生み出してしまうあのメソッドが、なんとここに来て役に立ってしまいました。Microsoftのおじさんもこう使われることを想定していたのでしょうか。

ともあれ、.NETで正確に文字列のサイズを計測するのには2度手間が掛かります。たぶん。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?