C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: 可変枠に収まるFont.Sizeの取得方法


(過去ログ 57 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■32673 / inTopicNo.1)  可変枠に収まるFont.Sizeの取得方法
  
□投稿者/ たこやき (87回)-(2009/02/12(Thu) 15:29:16)

分類:[C#] 

VS2008 C#
いつもお世話になっています。
可変枠にぴったり収まるフォントサイズを取得したいと思っているのですが、
わかりません。
一応 MeasureStringで調べる方法は考えてみたのですが、
もう少し効率的で簡単な方法はないでしょうか?
ご指導よろしくお願いいたします。

        private void button1_Click(object sender, EventArgs e)
        {
            Graphics g = this.CreateGraphics();
            Rectangle rect = new Rectangle(0, 0, 120, 150);

            int a = フォントサイズ("あ", rect.Size, g);
            Font f = new Font("MS 明朝", a);

            g.DrawRectangle(Pens.Red, rect);
            g.DrawString("あ", f, Brushes.Red, rect);
            g.Dispose();
        }

        // MeasureStringが返すサイズが指定枠のサイズを超えたら終了して、
        // Widthか Heightの小さい数字をフォントサイズとして返す。
        int フォントサイズ(String str,  Size mySize, Graphics g)
        {
            int A=0,B=0;
            bool fgA=false, fgB=false;

            for (int i = 1; i < 1000; i++)
            {
                Font f = new Font("MS 明朝", i);
                SizeF s = g.MeasureString(str, f);
                if (s.Width < mySize.Width)
                {
                    A = i;
                }
                else
                {
                    fgA = true; 
                }
                if (s.Height < mySize.Height) 
                {
                    B = i; 
                }
                else
                {
                    fgB = true; 
                }
                if (fgA && fgB) break;
            }
            return (A > B) ? B : A;
        }


引用返信 編集キー/
■32676 / inTopicNo.2)  Re[1]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ επιστημη (1707回)-(2009/02/12(Thu) 15:59:39)
επιστημη さんの Web サイト
> 一応 MeasureStringで調べる方法は考えてみたのですが、
> もう少し効率的で簡単な方法はないでしょうか?

「MeasureStringを使って効率的に」であれば二分法で挟み撃ちにしてはいかがでしょ。

引用返信 編集キー/
■32686 / inTopicNo.3)  Re[2]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ たこやき (88回)-(2009/02/12(Thu) 17:20:04)
No32676 (επιστημη さん) に返信
いつもありがとうございます。

> 「MeasureStringを使って効率的に」であれば二分法で挟み撃ちにしてはいかがでしょ。
効率が上がる分、ソースがさらに複雑になるような……。

MeasureStringを使わない方法か、
MeasureStringを使うとしても、引数の設定の仕方
例えば、public SizeF MeasureString(string text, Font font,int width)のwidthの
設定の仕方で簡単にできないものかと……。
public SizeF MeasureString(
string text,
Font font,
int width
)

public SizeF MeasureString(
string text,
Font font,
SizeF layoutArea
)
の使い方がよくわからないんですよ。


引用返信 編集キー/
■32696 / inTopicNo.4)  Re[1]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ よねKEN (261回)-(2009/02/12(Thu) 21:48:58)
2009/02/12(Thu) 21:51:11 編集(投稿者)
> もう少し効率的で簡単な方法はないでしょうか?

即興で書いたのでソースコードの見栄えはいまいちですが、
以下のような方向性でやるとよいのではないでしょうか。(ちゃちゃっと動作を見た程度ですので、テストは不十分です)

やっていること。
・枠の高さがフォントの最大の高さなので、枠の高さのフォントで文字列が枠内に収まるかを判定する
 →枠内に収まっているのであれば、このフォントがMAX → 判定終了
・枠内に収まっていないのであれば、枠の幅を超えてしまっているので、枠の高さをいくらか減らした高さにする必要がある。
 →枠の幅と実測の幅の比率から幅が枠に収まる高さを求める → 判定終了

ポイントは、フォントの高さを計算の基準として使っていることと、ピクセル指定でフォントを作っているところでしょうか。

処理時間は私の環境でのてきとうな計測で1/25〜1/30になりました。
コードも短くなります。ちなみに、"あ"の代わりに"I"で試したら、
"フォントサイズ"メソッドは89ポイント、私の"フォントサイズ2"メソッドは112ポイントを返しました。
(112ポイントでも四角形の枠内におさまってました)

#メソッド名だけちょっと変えてますが、メソッドのインタフェースは元のソースに準拠しています。

        // MeasureStringが返すサイズが指定枠のサイズを超えたら終了して、
        // Widthか Heightの小さい数字をフォントサイズとして返す。
        int フォントサイズ2(String str, Size mySize, Graphics g)
        {

            int prefferedSizeInPoints;
            int prefferedHeight = mySize.Height;
            Font f = new Font("MS 明朝", prefferedHeight, GraphicsUnit.Pixel);
            SizeF s = g.MeasureString(str, f);
            if (s.Width < mySize.Width)
            {
                prefferedSizeInPoints = (int)f.SizeInPoints;
            }
            else
            {
                prefferedHeight = (int)(prefferedHeight * mySize.Width / s.Width);
                f.Dispose();
                f = new Font("MS 明朝", prefferedHeight, GraphicsUnit.Pixel);
                prefferedSizeInPoints = (int)f.SizeInPoints;
            }
            f.Dispose();
            return prefferedSizeInPoints;
        }

引用返信 編集キー/
■32722 / inTopicNo.5)  Re[2]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ たこやき (89回)-(2009/02/13(Fri) 11:01:24)
No32696 (よねKEN さん) に返信
たいへんご丁寧な返信、ありがとうございました。
FormをResizeして確認させていただきましたが、
間違いなく動きます。

それで「よねKENさん」の計算方法を応用させていただき、
次のようにさせていただきました。

        int フォントサイズ3(String str, Size mySize, Graphics g)
        {
            SizeF s = g.MeasureString(str, new Font("MS 明朝", 1));
            int a = (int)(mySize.Width / s.Width);
            int b = (int)(mySize.Height / s.Height);
            return (a < b) ? a : b;
        }

これでも一応はうまくできたのですが、「よねKENさん」の方が
やや大きな字になります。
本当にありがとうございました。


参考までに双方のテストソースを記載します。
        private void Form1_Resize(object sender, EventArgs e)
        {
            フォントサイズ計測();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            フォントサイズ計測();
        }

        void フォントサイズ計測()
        {
            Graphics g = this.CreateGraphics();
            g.Clear(Color.White);

            int p2 = フォントサイズ2(textBox1.Text, this.ClientSize, g);
            int p3 = フォントサイズ3(textBox1.Text, this.ClientSize, g);
            Font f2 = new Font("MS 明朝", p2);
            Font f3 = new Font("MS 明朝", (p3>0?p3:1));

            g.DrawString(textBox1.Text, f2, Brushes.Red, this.ClientRectangle);
            g.DrawString(textBox1.Text, f3, Brushes.Blue, this.ClientRectangle);
            g.Dispose();        
        }

        int フォントサイズ2(String str, Size mySize, Graphics g)
        {
            int prefferedSizeInPoints;
            int prefferedHeight = mySize.Height;
            Font f = new Font("MS 明朝", prefferedHeight, GraphicsUnit.Pixel);
            SizeF s = g.MeasureString(str, f);
            if (s.Width < mySize.Width)
            {
                prefferedSizeInPoints = (int)f.SizeInPoints;
            }
            else
            {
                prefferedHeight = (int)(prefferedHeight * mySize.Width / s.Width);
                f.Dispose();
                f = new Font("MS 明朝", prefferedHeight, GraphicsUnit.Pixel);
                prefferedSizeInPoints = (int)f.SizeInPoints;
            }
            f.Dispose();
            return prefferedSizeInPoints;
        }

        int フォントサイズ3(String str, Size mySize, Graphics g)
        {
            SizeF s = g.MeasureString(str, new Font("MS 明朝", 1));
            int a = (int)(mySize.Width / s.Width);
            int b = (int)(mySize.Height / s.Height);
            return (a < b) ? a : b;
        }




解決済み
引用返信 編集キー/
■32730 / inTopicNo.6)  Re[3]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ よねKEN (263回)-(2009/02/13(Fri) 11:56:47)
2009/02/13(Fri) 11:59:13 編集(投稿者)
>         int フォントサイズ3(String str, Size mySize, Graphics g)
>         {
>             SizeF s = g.MeasureString(str, new Font("MS 明朝", 1));
>             int a = (int)(mySize.Width / s.Width);
>             int b = (int)(mySize.Height / s.Height);
>             return (a < b) ? a : b;
>         }

素晴らしくコンパクトになって良いですね。
 
> これでも一応はうまくできたのですが、「よねKENさん」の方が
> やや大きな字になります。

より厳格なポイントを求めたいなら別ですが、だいたいでよければ、フォントサイズ3の方法もとてもいいですね。

ところで、フォントサイズを求めるメソッドですから、何度も呼ばれるメソッドだと思います。
なので以下のようにFontもきちんとDisposeしておいた方がなおよいでしょう。

int フォントサイズ3(String str, Size mySize, Graphics g)
{
    SizeF s;
    using (Font f = new Font("MS 明朝", 1))
    {
        s = g.MeasureString(str, f);
    }
    int a = (int)(mySize.Width / s.Width);
    int b = (int)(mySize.Height / s.Height);
    return (a < b) ? a : b;
}

解決済み
引用返信 編集キー/
■32735 / inTopicNo.7)  Re[4]: 可変枠に収まるFont.Sizeの取得方法
□投稿者/ たこやき (91回)-(2009/02/13(Fri) 12:32:33)
No32730 (よねKEN さん) に返信

> 素晴らしくコンパクトになって良いですね。
投稿89回にして初めてほめられました。ありがとうございます。
よねKENさんのヒントがあってのことですが……。

> using (Font f = new Font("MS 明朝", 1))
> {
> s = g.MeasureString(str, f);
> }

ド素人なもんで、usingの使い方と使う対象が分かりにくく、
ガベージコレクションに任せっきりでしたが、
勉強になりました。今後はもう少し気をつけたいと思います。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -