あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

【C#】Labelコントロールでテキストフォントのサイズを自動調節する

 現在携わっているブロジェクトで実装した内容をメモ代わりに残そうと思います。
Excelでいうところの「縮小して全体を表示する」をWindowsFormのLabelコントロールで実装する要件が出てきた為、コントロールの矩形サイズから自動でフォントサイズを調節するユーザコントロールを作成しました。
 WindowsFormのC#業務アプリはまだしばらく無くならないと思いますので、今後のプロジェクトの参考資料かな…。

namespace WindowsFormsApplication1
{
  partial class AutoFontSizeLabel
  {
    /// <summary>
    /// 必要なデザイナー変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region コンポーネント デザイナーで生成されたコード

    /// <summary>
    /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
    /// コード エディターで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
      this.SuspendLayout();
      this.ResumeLayout(false);
    }

    #endregion
  }
}


 CalcFontSizeメソッドはMeasureStringメソッドを呼び出す際、引数の文字列が空文字の場合、SizeFが正しく計算されないため、空文字が引数で渡ってきた場合、初期値にそれぞれ0.1を設定しています。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
  public partial class AutoFontSizeLabel : Label
  {
    #region クラス変数
    /// <summary>
    /// フォントサイズを自動で算出するかのフラグ
    /// </summary>
    private bool mAutoFontSize = false;
    #endregion

    #region プロパティ
    /// <summary>
    /// フォントサイズを自動計算するかの値を取得または設定します。
    /// </summary>
    [Browsable(true)]
    [Category("表示")]
    [Description("フォントサイズを自動で計算するかの値を取得または設定します。")]
    public bool AutoFontSize
    {
      set
      {
        this.mAutoFontSize = value;
        Invalidate();
      }
      get
      {
        return this.mAutoFontSize;
      }
    }
    #endregion

    #region コンストラクタ
    /// <summary>
    /// クラスの新しいインスタンスを初期化します。
    /// </summary>
    public AutoFontSizeLabel()
    {
      InitializeComponent();
    }
    #endregion

    #region overrideメソッド
    /// <summary>
    /// 描画処理
    /// </summary>
    /// <param name="pevent"></param>
    protected override void OnPaint(PaintEventArgs pevent)
    {
      // 描画先のGraphicsオブジェクトを取得する
      var g = pevent.Graphics;

      // 描画に関連する値をコントロールのプロパティ等から取得する
      int height = this.Height;
      int width = this.Width;

      // 描画領域を指定する
      var rect = new Rectangle(0, 0, width, height);

      // 背景描画用のブラシを生成する
      using (backColorBrush = new SolidBrush(this.BackColor))
      {
        // 背景を描画する
        g.FillRectangle(backColorBrush, rect);
      }

      var size = new Size(width, height);
      var fontSize = CalcFontSize(this.Text, size, g);

      var font = this.Font;

      if (this.mAutoFontSize)
      {
        // 自動算出する場合、計算しておいたフォントサイズでフォントのインスタンスを再生成する
        font = new Font(this.Font.Name, fontSize);
      }

      // StringAlignmentからContentAlignmentへ変換する
      var stringFormat = new StringFormat();
      var num = (Int32)System.Math.Log((Double)this.TextAlign, 2);
      stringFormat.LineAlignment = (StringAlignment)(num / 4);
      stringFormat.Alignment = (StringAlignment)(num % 4);

      // 文字描画用のブラシを生成する
      using (var foreColorBrush = new SolidBrush(this.ForeColor))
      {
        // 文字を描画する
        g.DrawString(this.Text, font, foreColorBrush, rect, stringFormat);
      }
    }
    #endregion

    #region privateメソッド
    /// <summary>
    /// 引数で指定されたグラフィックオブジェクトに描画する最適なフォントサイズを算出します。
    /// </summary>
    /// <param name="str">出力する文字列</param>
    /// <param name="size">サイズ</param>
    /// <param name="g">グラフィックオブジェクト</param>
    /// <returns>フォントサイズ</returns>
    private float CalcFontSize(string str, Size size, Graphics g)
    {
      var s = new SizeF(0.1F, 0.1F);
      var a = 0.1F;
      var b = 0.1F;

      if (!string.IsNullOrEmpty(str))
      {
        s = g.MeasureString(str, new Font(this.Font.Name, this.Font.Size));
        a = (size.Width / s.Width);
        b = (size.Height / s.Height);
      }
      return (a < b) ? a : b;
    }
    #endregion
  }
}


 DrawStringメソッドで文字を描画すると微妙に右にずれます。掲示板などで色々議論されていますが、今回未対応です。以下のサイトが参考になるかと思います。
VB.netで文字を正確な位置に描く。