はじめに
Windows Forms の MonthCalendar は、HitTest(Point) でマウス座標から「どの部位(セル/ボタン/タイトル/今日はココ など)をクリックしたか」を判定できます。日付セルだけでなく、前月/翌月ボタンや曜日ヘッダー、タイトル帯なども識別できるため、部位ごとに挙動を変える実装が簡単になります。
説明
HitTest(Point) は MonthCalendar.HitTestInfo を返します。主なプロパティは以下の通りです。
・HitArea:クリック部位(Date / NextMonthButton / PrevMonthButton / CalendarHeader / Title / TodayLink など)
・Time:部位が Date のとき、その日付が入る(それ以外は DateTime.MinValue)
この戻り値を使って、日付セルなら詳細ポップアップ、前後月ボタンならログ、タイトルクリックで並び替え、など柔軟に分岐できます。
サンプルコード(極力短く)
マウスダウン位置の部位と日付をトースト表示するだけの最小例です。
using System;
using System.Windows.Forms;
class MainForm : Form
{
MonthCalendar cal = new MonthCalendar { Dock = DockStyle.Fill };
public MainForm()
{
Text = "MonthCalendar - HitTest(Point)";
Controls.Add(cal);
cal.MouseDown += (s, e) =<
{
var hit = cal.HitTest(e.Location);
string msg = hit.HitArea.ToString();
if (hit.HitArea == MonthCalendar.HitArea.Date)
msg += $" : {hit.Time:yyyy-MM-dd}";
// 例: 前後月ボタンやTodayLinkなども判別可
// if (hit.HitArea == MonthCalendar.HitArea.NextMonthButton) { ... }
// さっと確認できる簡易表示
var tip = new ToolTip();
tip.Show(msg, cal, e.Location, 1500);
};
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
}
つまづきポイント
1) 日付が取れない
Time は HitArea == Date のときだけ有効です。ヘッダーやボタンでは DateTime.MinValue になります。
2) 座標はクライアント座標で渡す
HitTest に渡すのは MonthCalendar のクライアント座標です。マウスイベント(MouseDown など)の e.Location をそのまま使えばOK。
3) 複数月表示でも判定できる?
はい。CalendarDimensions で複数月表示でも、クリック位置に対応する正しい HitArea/Time が返ります。
まとめ
HitTest(Point) を使えば、「どこが押されたか」をピンポイントに把握できます。日付セルとその他の部位を分けて処理するだけで、操作感のよいカレンダー連携 UI を短いコードで実現できます。

コメント