by WebSurfer
2017年11月4日 14:32
Windows Forms アプリケーション用に、カレンダーを表示してユーザーが日付を選択できる MonthCalendar コントロールがあります。
その Size プロパティから MonthCalendar のサイズを取得する際、タイミングによっては正しいサイズが取得できない、その場合でもデバッガで MonthCalendar を開いてその中身を見ると正しいサイズになるという不可解なことがありました。
具体的には、下のコードの Button_Click メソッドをデバッガでステップ実行させ、コメント (3) の行で止めて Size プロパティを見ると 178 x 155 となっているが、calendar の中身をデバッガで開いて見た後で Size プロパティを見ると 199 x 162 と正しい値になるというものです。
その理由を調べたので備忘録として書いておきます。なお、元の話は Teratail のスレッド「VisualStudioでデバッグ中にプロパティの値が変化する」です。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Button button = new Button();
button.Click += Button_Click;
this.Controls.Add(button);
}
private void Button_Click(object sender, EventArgs e)
{
Form f = new Form();
Size size1 = f.Size; // (1) W: 300, H: 300
f.Size = new Size(200, 200);
size1 = f.Size; // (2) W: 200, H: 200
MonthCalendar calendar = new MonthCalendar();
Size size2 = calendar.Size; // (3) W: 178, H: 155
calendar.Size = new Size(200, 200);
size2 = calendar.Size; // (4) W: 178, H: 155
f.Controls.Add(calendar);
size2 = calendar.Size; // (5) W: 178, H: 155
f.Show();
size2 = calendar.Size; // (6) W: 199, H: 162
f.ClientSize = calendar.Size;
}
}
}
上に書いた「不可解なこと」の理由は、多少想像が入っていますが、以下のようなことだと思われます。
-
MonthCalendar のサイズを決定するのは使用されるフォントのみ。MonthCalendar.Size プロパティの設定では変えられない・・・コメント (4) 参照。
-
new MonthCalendar() の時点ではフォントが不明なので MonthCalendar のサイズは未定。
-
コメント (3) の時点で Size プロパティを見ると 178 x 155 となっているが、それはデフォルト値でフォントを反映した正しいサイズではない。
-
コメント (3) の時点で calendar.Size の calendar にマウスカーソルを当てて開くと、その時点で calendar が初期化され、使用されるフォントに応じて正しいサイズが Size プロパティに設定される。
-
その後で calendar.Size の Size にマウスカーソルを当てると正しいサイズ 199 x 162 が取得できる。
-
デバッガで calendar を開いて見るということをしなければ、使用されるフォントに応じて正しいサイズが Size プロパティに設定されるのは、上記のコードでは f.Show(); の時点。
-
その後であれば、calendar.Size で正しいサイズを取得でき、それを Form の ClientSize に設定してやれば上の画像の通り calendar がフォーム内にぴったり収まる。
上のことを書いた Microsoft の公式文書などは見つからないのですが、コードで検証した結果が上記の想像は正しいことを裏付けていると思います。