【VB.NET】MonthCalendarを「ただのカレンダー」で終わらせない!業務効率を爆上げするカスタム描画術
こんにちは。現場の「自動化」と「UIの最適化」をこよなく愛するエンジニアです。
皆さんは、社内ツールで日付を選択させる際、標準の `MonthCalendar` コントロールをそのまま使っていませんか?「今日が休日なのか」「繁忙期で納期はいつまでか」——そんな情報がカレンダー上にパッと表示されたら、ユーザーはどれほど楽になるでしょうか。
今回は、標準コントロールの枠を超え、「視覚的に情報を伝えるカレンダー」を実装する技術を伝授します。マクロの記録から一歩踏み出し、真のWindows開発者への階段を一緒に登りましょう。
—
なぜ、標準機能だけでは足りないのか?
標準の `MonthCalendar` は日付選択には便利ですが、「特定の日付をハイライトする」「背景に色をつける」といった柔軟なカスタマイズが極めて困難です。実は、このコントロールはWindows APIの深い部分で制御されており、通常のプロパティ設定だけでは色が変えられない仕様になっています。
ここで、「じゃあ諦めるしかないの?」と考えるのはまだ早い。我々エンジニアは、「描画処理(Paintイベント)を乗っ取る」という魔法を使います。
—
ステップ1:準備運動と基本的な考え方
VB.NETでカスタムUIを作る際、忘れてはいけないのが「描画の主導権を握る」ことです。今回はコントロール全体を覆うようにグラフィックを描画するアプローチを取ります。
まずは、フォームに `MonthCalendar` を配置し、以下の準備をしてください。
1. `MonthCalendar` の `DrawMode` プロパティが存在しないため、あえて標準の枠組みを活かしつつ、「重ねる」手法をとります。
2. 今回は分かりやすく、選択されている日付に関連する情報を「ツールチップ」で表示する実装から始めましょう。
—
ステップ2:実践!日付に命を吹き込むコード
以下のコードは、カレンダーで日付が選択された瞬間に、その日が「稼働日か休日か」を判定し、ツールチップで知らせる実装です。
‘ フォームのロード時にツールチップを初期化
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
‘ ツールチップの設定
ToolTip1.IsBalloon = True
ToolTip1.AutoPopDelay = 5000
End Sub
‘ 日付が変更されたときにイベントをフックする
Private Sub MonthCalendar1_DateChanged(sender As Object, e As DateRangeEventArgs) Handles MonthCalendar1.DateChanged
Dim selectedDate As Date = e.Start
‘ ここで社内カレンダーDBやロジックを参照
Dim status As String = GetBusinessStatus(selectedDate)
‘ ユーザーに情報を通知
ToolTip1.SetToolTip(MonthCalendar1, $”日付: {selectedDate.ToShortDateString()}” & vbCrLf & $”状況: {status}”)
End Sub
‘ 業務ロジック:簡易的な判定メソッド
Private Function GetBusinessStatus(d As Date) As String
If d.DayOfWeek = DayOfWeek.Saturday OrElse d.DayOfWeek = DayOfWeek.Sunday Then
Return “【休日】お休みです”
ElseIf d.Month = 12 And d.Day = 25 Then
Return “【繁忙期】年末特別稼働日”
Else
Return “【通常】稼働日”
End If
End Function
—
ステップ3:陥りやすい「罠」と解決策
ここが一番のポイントです。初心者がよく陥るミスが「イベントの連鎖」です。
- 罠: `DateChanged` イベント内で `MonthCalendar` の設定を頻繁に変更しようとすると、再描画処理が走ってイベントが無限ループ(スタックオーバーフロー)を起こすことがあります。
- 対策: 描画処理が必要な場合は、`Invalidate()` メソッドを呼び出し、必要なタイミングでのみ「再描画要求」を出すのがプロの作法です。
—
さらに先へ:視覚的なハイライトを極めるなら
もし、本当にカレンダーの日付背景を赤や青に染め上げたいのであれば、`MonthCalendar` を継承したクラスを作成し、`WndProc`(Windowsメッセージプロシージャ)をオーバーライドして、WM_PAINTメッセージを直接キャッチする必要があります。
これは少しレベルが高いですが、VB.NETの「クラス継承」と「API操作」を学ぶ最高の題材です。
学習のヒント
- 継承(Inherits MonthCalendar): 標準機能を拡張する基本です。
- イベント駆動: 「何かが起きたら動く」ではなく「状態が変わったことを監視する」という意識を持ってください。
—
まとめ:自動化の先にある「使いやすさ」
今回紹介した「ツールチップによる情報提示」は、わずか数行のコードですが、ユーザーにとっては「マニュアルを見なくても状況がわかる」という強力なUX(ユーザーエクスペリエンス)の向上に繋がります。
VB.NETは古い言語だと言われることもありますが、Windowsの深い部分まで制御できる唯一無二のツールです。ぜひ、標準機能に満足せず、あなただけの「賢いカレンダー」を作ってみてください。
「ここが動かない!」「もっと高度な描画はどうやるの?」という質問があれば、いつでも聞いてくださいね。現場の壁を一つずつ一緒に突破していきましょう!
