はじめに
Windowsフォームアプリケーションで日付を入力する際、デフォルトの日付ピッカー(DateTimePicker)を使用するのが一般的ですが、デザインや機能をカスタマイズしたい場合には適していません。本記事では、TextBox をベースにしたカスタム日付ピッカーの実装方法を紹介します。
本カスタム日付ピッカーでは、以下のような機能を提供します。
- TextBox 内に日付を表示
- MonthCalendar をポップアップ表示
- BackColorをカスタマイズ可能
- カスタムのカレンダーアイコンを追加可能
- 初期選択デートやリセット機能の実装
実装方法
1. CustomDatePickerDemo クラスの作成
TextBox を継承して、クリックすると MonthCalendar を表示するカスタム日付ピッカーを作成します。
public class CustomDatePickerDemo : TextBox
{
private MonthCalendar monthCalendar;
private Form popupForm;
private Form parentForm;
// 選択された日付を取得および設定するための SelectedDate プロパティ
private DateTime selectedDate = DateTime.Now;
public DateTime SelectedDate
{
get { return selectedDate; }
set
{
selectedDate = value;
// カレンダーの日付を設定
if (monthCalendar != null)
{
monthCalendar.SetDate(selectedDate);
}
// TextBox のテキストを選択された日付で更新
this.Text = selectedDate.ToString("yyyy年MM月dd日");
}
}
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
if (this.Parent != null)
{
parentForm = this.FindForm();
if (parentForm != null)
{
parentForm.MouseDown += ParentForm_MouseDown; // TextBox 外部のクリックを検出
}
}
}
private void ShowCalendar()
{
if (popupForm != null)
{
popupForm.Close();
popupForm = null;
}
popupForm = new Form
{
FormBorderStyle = FormBorderStyle.None,
ShowInTaskbar = false,
StartPosition = FormStartPosition.Manual,
AutoSize = false,
};
monthCalendar = new MonthCalendar
{
MaxSelectionCount = 1
};
// テキストが空の場合、カレンダーの選択日を現在の日付に設定
if (string.IsNullOrEmpty(this.Text))
{
monthCalendar.SetDate(DateTime.Now);
}
else
{
// テキストが空でない場合、カレンダーの選択日を現在の SelectedDate に設定
monthCalendar.SetDate(SelectedDate);
}
// カレンダーが表示されたときに選択日を設定
monthCalendar.DateSelected += MonthCalendar_DateSelected;
popupForm.Controls.Add(monthCalendar);
// カレンダーのサイズに基づいてポップアップのサイズを調整
popupForm.ClientSize = new Size(
monthCalendar.Width + 48,
monthCalendar.Height + 6
);
// TextBox の下にポップアップを配置
Point screenLocation = this.PointToScreen(new Point(0, this.Height));
popupForm.Location = screenLocation;
popupForm.Deactivate += (s, e) => CloseCalendar();
popupForm.Show();
}
private void MonthCalendar_DateSelected(object sender, DateRangeEventArgs e)
{
// カレンダーで日付が選択されたときに、TextBox のテキストを更新
this.Text = e.Start.ToString("yyyy年MM月dd日");
// SelectedDate プロパティを更新
SelectedDate = e.Start;
CloseCalendar();
if (parentForm != null)
{
parentForm.ActiveControl = null; // TextBox からフォーカスを外す
}
}
private void ParentForm_MouseDown(object sender, MouseEventArgs e)
{
if (popupForm == null)
return;
Point mousePosition = parentForm.PointToScreen(e.Location);
if (this.Bounds.Contains(this.Parent.PointToClient(mousePosition)))
return;
if (popupForm.Bounds.Contains(mousePosition))
return;
// クリックが外部だった場合、カレンダーを閉じる
CloseCalendar();
}
private void CloseCalendar()
{
if (popupForm != null)
{
popupForm.Close();
popupForm = null
}
}
}
2. BackColorのカスタマイズ
CustomBackColor プロパティを追加することで、TextBox の背景色を変更できます。
public Color CustomBackColor
{
get { return this.BackColor; }
set { this.BackColor = value; }
}
3. カレンダーアイコンの追加
カレンダーアイコンを PictureBox で追加し、クリック時に ShowCalendar() を実行することで、より直感的なUIを実現できます。
private PictureBox calendarIcon;
public CustomDatePickerDemo()
{
calendarIcon = new PictureBox
{
Image = Properties.Resources.calendarDark, // 画像リソースを指定
SizeMode = PictureBoxSizeMode.StretchImage,
Size = new Size(20, 20),
Cursor = Cursors.Hand,
Location = new Point(this.Width + 28, (this.Height - 20) / 2),
BackColor = Color.Transparent
};
this.Controls.Add(calendarIcon);
calendarIcon.Click += (s, e) => ShowCalendar();
this.Click += (s, e) => ShowCalendar();
}
4.フォームでの利用
CustomDatePickerDemo をフォームに追加し、複数の TextBox に適用できます。
public partial class CustomDatePickerForm : Form
{
public CustomDatePickerDemo customDatePicker;
public CustomDatePickerForm()
{
InitializeComponent();
customDatePicker = new CustomDatePickerDemo
{
Location = new Point(45, 20),
Width = 150,
CustomBackColor = Color.Yellow
};
this.panel1.Controls.Add(customDatePicker);
CustomDatePickerDemo customDatePicker2 = new CustomDatePickerDemo
{
Location = new Point(45, 20),
Width = 150,
CustomBackColor = Color.Yellow,
SelectedDate = new DateTime(2022, 3, 2)
};
this.panel2.Controls.Add(customDatePicker2);
}
private void btnOk_Click(object sender, EventArgs e)
{
MessageBox.Show(customDatePicker.SelectedDate.ToString("yyyy年MM月dd日"));
}
}
5. リセット機能の実装
リセットボタンをクリックすると、TextBox の内容をクリアし、カレンダーを開く際には最小日付を設定します。
private void reset_Click(object sender, EventArgs e)
{
customDatePicker.Text = "";
}
まとめ
本記事では、カスタム日付ピッカーの実装方法について解説しました。TextBox をベースに MonthCalendar をポップアップ表示し、背景色の変更やカレンダーアイコンの追加、リセット機能を実装しました。
このカスタム日付ピッカーを活用することで、デザインの自由度を高めつつ、ユーザーにとって使いやすいUIを提供できます。