Files
Winforms-Calendar/WindowsFormsCalendar/UserControls/MonthView.cs
2019-04-23 12:29:22 -07:00

1026 lines
33 KiB
C#

/*
Copyright 2012 Justin LeCheminant
This file is part of WindowsFormsCalendar.
indowsFormsCalendar is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
indowsFormsCalendar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with indowsFormsCalendar. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsCalendar
{
/// <summary>
/// Hosts a month-level calendar where user can select day-based dates
/// </summary>
[DefaultEvent("SelectionChanged")]
public class MonthView
: ContainerControl
{
#region Fields
private int _forwardMonthIndex;
private MonthViewDay _lastHitted;
private bool _mouseDown;
private Size _daySize;
private DateTime _selectionStart;
private DateTime _selectionEnd;
private string _monthTitleFormat;
private DayOfWeek _weekStart;
private DayOfWeek _workWeekStart;
private DayOfWeek _workWeekEnd;
private MonthViewSelection _selectionMode;
private string _dayNamesFormat;
private bool _dayNamesVisible;
private int _dayNamesLength;
private DateTime _viewStart;
private Size _monthSize;
private MonthViewMonth[] _months;
private Padding _itemPadding;
private Color _monthTitleColor;
private Color _monthTitleColorInactive;
private Color _monthTitleTextColor;
private Color _monthTitleTextColorInactive;
private Color _dayBackgroundColor;
private Color _daySelectedBackgroundColor;
private Color _dayTextColor;
private Color _daySelectedTextColor;
private Color _arrowsColor;
private Color _arrowsSelectedColor;
private Color _dayGrayedText;
private Color _todayBorderColor;
private int _maxSelectionCount;
private Rectangle _forwardButtonBounds;
private bool _forwardButtonSelected;
private Rectangle _backwardButtonBounds;
private bool _backwardButtonSelected;
#endregion
#region Events
/// <summary>
/// Occurs when selection has changed.
/// </summary>
public event EventHandler SelectionChanged;
#endregion
#region Properties
/// <summary>
/// Gets the size of days rectangles
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public Size DaySize
{
get { return _daySize; }
}
/// <summary>
/// Gets or sets the format of day names
/// </summary>
[DefaultValue( "ddd" )]
public string DayNamesFormat
{
get { return _dayNamesFormat; }
set { _dayNamesFormat = value; }
}
/// <summary>
/// Gets or sets a value indicating if day names should be visible
/// </summary>
[DefaultValue( true )]
public bool DayNamesVisible
{
get { return _dayNamesVisible; }
set { _dayNamesVisible = value; }
}
/// <summary>
/// Gets or sets how many characters of day names should be displayed
/// </summary>
[DefaultValue( 2 )]
public int DayNamesLength
{
get { return _dayNamesLength; }
set { _dayNamesLength = value; UpdateMonths(); }
}
/// <summary>
/// Gets or sets what the first day of weeks should be
/// </summary>
[DefaultValue( DayOfWeek.Sunday )]
public DayOfWeek FirstDayOfWeek
{
get { return _weekStart; }
set { _weekStart = value; }
}
/// <summary>
/// Gets a value indicating if the backward button is selected
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public bool BackwardButtonSelected
{
get { return _backwardButtonSelected; }
}
/// <summary>
/// Gets the bounds of the backward button
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public Rectangle BackwardButtonBounds
{
get { return _backwardButtonBounds; }
}
/// <summary>
/// Gets a value indicating if the forward button is selected
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public bool ForwardButtonSelected
{
get { return _forwardButtonSelected; }
}
/// <summary>
/// Gets the bounds of the forward button
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public Rectangle ForwardButtonBounds
{
get { return _forwardButtonBounds; }
}
/// <summary>
/// Gets or sets the Font of the Control
/// </summary>
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
UpdateMonthSize();
UpdateMonths();
}
}
/// <summary>
/// Gets or sets the internal padding of items (Days, day names, month names)
/// </summary>
public Padding ItemPadding
{
get { return _itemPadding; }
set { _itemPadding = value; }
}
/// <summary>
/// Gets or sets the maximum selection count of days
/// </summary>
[DefaultValue( 0 )]
public int MaxSelectionCount
{
get { return _maxSelectionCount; }
set { _maxSelectionCount = value; }
}
/// <summary>
/// Gets the Months currently displayed on the calendar
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public MonthViewMonth[] Months
{
get { return _months; }
}
/// <summary>
/// Gets the size of an entire month inside the <see cref="MonthView"/>
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public Size MonthSize
{
get { return _monthSize; }
}
/// <summary>
/// Gets or sets the format of month titles
/// </summary>
[DefaultValue( "MMMM yyyy" )]
public string MonthTitleFormat
{
get { return _monthTitleFormat; }
set { _monthTitleFormat = value; UpdateMonths(); }
}
/// <summary>
/// Gets or sets the start of selection
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public DateTime SelectionStart
{
get { return _selectionStart; }
set
{
if( MaxSelectionCount > 0 )
{
if( Math.Abs( value.Subtract( SelectionEnd ).TotalDays ) >= MaxSelectionCount )
{
return;
}
}
_selectionStart = value;
Invalidate();
OnSelectionChanged( EventArgs.Empty );
}
}
/// <summary>
/// Gets or sets the end of selection
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public DateTime SelectionEnd
{
get { return _selectionEnd; }
set
{
if( MaxSelectionCount > 0 )
{
if( Math.Abs( value.Subtract( SelectionStart ).TotalDays ) >= MaxSelectionCount )
{
return;
}
}
_selectionEnd = value.Date.Add( new TimeSpan( 23, 59, 59 ) );
Invalidate();
OnSelectionChanged( EventArgs.Empty );
}
}
/// <summary>
/// Gets or sets the selection mode of <see cref="MonthView"/>
/// </summary>
[DefaultValue( MonthViewSelection.Manual )]
public MonthViewSelection SelectionMode
{
get { return _selectionMode; }
set { _selectionMode = value; }
}
/// <summary>
/// Gets or sets the date of the first displayed month
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
public DateTime ViewStart
{
get { return _viewStart; }
set { _viewStart = value; UpdateMonths(); Invalidate(); }
}
/// <summary>
/// Gets the last day of the last month showed on the view.
/// </summary>
public DateTime ViewEnd
{
get
{
DateTime month = Months[Months.Length - 1].Date;
return month.Date.AddDays( DateTime.DaysInMonth( month.Year, month.Month ) );
}
}
/// <summary>
/// Gets or sets the day that starts a work-week
/// </summary>
[DefaultValue( DayOfWeek.Monday )]
public DayOfWeek WorkWeekStart
{
get { return _workWeekStart; }
set { _workWeekStart = value; }
}
/// <summary>
/// Gets or sets the day that ends a work-week
/// </summary>
[DefaultValue( DayOfWeek.Friday )]
public DayOfWeek WorkWeekEnd
{
get { return _workWeekEnd; }
set { _workWeekEnd = value; }
}
#endregion
#region Color Properties
/// <summary>
/// Gets or sets the color of the arrows selected.
/// </summary>
/// <value>
/// The color of the arrows selected.
/// </value>
public Color ArrowsSelectedColor
{
get { return _arrowsSelectedColor; }
set { _arrowsSelectedColor = value; }
}
/// <summary>
/// Gets or sets the color of the arrows.
/// </summary>
/// <value>
/// The color of the arrows.
/// </value>
public Color ArrowsColor
{
get { return _arrowsColor; }
set { _arrowsColor = value; }
}
/// <summary>
/// Gets or sets the color of the day selected text.
/// </summary>
/// <value>
/// The color of the day selected text.
/// </value>
public Color DaySelectedTextColor
{
get { return _daySelectedTextColor; }
set { _daySelectedTextColor = value; }
}
/// <summary>
/// Gets or sets the color of the day selected.
/// </summary>
/// <value>
/// The color of the day selected.
/// </value>
public Color DaySelectedColor
{
get { return _dayTextColor; }
set { _dayTextColor = value; }
}
/// <summary>
/// Gets or sets the color of the day selected background.
/// </summary>
/// <value>
/// The color of the day selected background.
/// </value>
public Color DaySelectedBackgroundColor
{
get { return _daySelectedBackgroundColor; }
set { _daySelectedBackgroundColor = value; }
}
/// <summary>
/// Gets or sets the color of the day background.
/// </summary>
/// <value>
/// The color of the day background.
/// </value>
public Color DayBackgroundColor
{
get { return _dayBackgroundColor; }
set { _dayBackgroundColor = value; }
}
/// <summary>
/// Gets or sets the day grayed text.
/// </summary>
/// <value>
/// The day grayed text.
/// </value>
public Color DayGrayedText
{
get { return _dayGrayedText; }
set { _dayGrayedText = value; }
}
/// <summary>
/// Gets or sets the color of the month title.
/// </summary>
/// <value>
/// The color of the month title.
/// </value>
public Color MonthTitleColor
{
get { return _monthTitleColor; }
set { _monthTitleColor = value; }
}
/// <summary>
/// Gets or sets the month title text color inactive.
/// </summary>
/// <value>
/// The month title text color inactive.
/// </value>
public Color MonthTitleTextColorInactive
{
get { return _monthTitleTextColorInactive; }
set { _monthTitleTextColorInactive = value; }
}
/// <summary>
/// Gets or sets the color of the month title text.
/// </summary>
/// <value>
/// The color of the month title text.
/// </value>
public Color MonthTitleTextColor
{
get { return _monthTitleTextColor; }
set { _monthTitleTextColor = value; }
}
/// <summary>
/// Gets or sets the month title color inactive.
/// </summary>
/// <value>
/// The month title color inactive.
/// </value>
public Color MonthTitleColorInactive
{
get { return _monthTitleColorInactive; }
set { _monthTitleColorInactive = value; }
}
/// <summary>
/// Gets or sets the color of the today day border color
/// </summary>
public Color TodayBorderColor
{
get { return _todayBorderColor; }
set { _todayBorderColor = value; }
}
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="MonthView"/> class.
/// </summary>
public MonthView()
{
SetStyle(ControlStyles.Opaque, true);
DoubleBuffered = true;
_dayNamesFormat = "ddd";
_monthTitleFormat = "MMMM yyyy";
_selectionMode = MonthViewSelection.Manual;
_workWeekStart = DayOfWeek.Monday;
_workWeekEnd = DayOfWeek.Friday;
_weekStart = DayOfWeek.Sunday;
_dayNamesVisible = true;
_dayNamesLength = 2;
_viewStart = DateTime.Now;
_itemPadding = new Padding(2);
_monthTitleColor = SystemColors.ActiveCaption;
_monthTitleColorInactive = SystemColors.InactiveCaption;
_monthTitleTextColor = SystemColors.ActiveCaptionText;
_monthTitleTextColorInactive = SystemColors.InactiveCaptionText;
_dayBackgroundColor = Color.Empty;
_daySelectedBackgroundColor = SystemColors.Highlight;
_dayTextColor = SystemColors.WindowText;
_daySelectedTextColor = SystemColors.HighlightText;
_arrowsColor = SystemColors.Window;
_arrowsSelectedColor = Color.Gold;
_dayGrayedText = SystemColors.GrayText;
_todayBorderColor = Color.Maroon;
UpdateMonthSize();
UpdateMonths();
}
#region Public Methods
/// <summary>
/// Checks if a day is hitted on the specified point
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public MonthViewDay HitTest(Point p)
{
for (int i = 0; i < Months.Length; i++)
{
if (Months[i].Bounds.Contains(p))
{
for (int j = 0; j < Months[i].Days.Length; j++)
{
if (/*Months[i].Days[j].Visible && */Months[i].Days[j].Bounds.Contains(p))
{
return Months[i].Days[j];
}
}
}
}
return null;
}
/// <summary>
/// Moves the view one month forward
/// </summary>
public void GoForward()
{
ViewStart = ViewStart.AddMonths(1);
}
/// <summary>
/// Moves the view one month backward
/// </summary>
public void GoBackward()
{
ViewStart = ViewStart.AddMonths(-1);
}
#endregion
#region Private Methods
/// <summary>
/// Sets the forward button bounds.
/// </summary>
/// <param name="bounds">The bounds.</param>
private void SetForwardButtonBounds(Rectangle bounds)
{
_forwardButtonBounds = bounds;
}
/// <summary>
/// Sets the backward button bounds.
/// </summary>
/// <param name="bounds">The bounds.</param>
private void SetBackwardButtonBounds(Rectangle bounds)
{
_backwardButtonBounds = bounds;
}
/// <summary>
/// Sets the forward button selected.
/// </summary>
/// <param name="selected">if set to <c>true</c> [selected].</param>
private void SetForwardButtonSelected(bool selected)
{
_forwardButtonSelected = selected;
Invalidate(ForwardButtonBounds);
}
/// <summary>
/// Sets the backward button selected.
/// </summary>
/// <param name="selected">if set to <c>true</c> [selected].</param>
private void SetBackwardButtonSelected(bool selected)
{
_backwardButtonSelected = selected;
Invalidate(BackwardButtonBounds);
}
/// <summary>
/// Selects the week where the hit is contained
/// </summary>
/// <param name="hit"></param>
private void SelectWeek(DateTime hit)
{
int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[(int)hit.DayOfWeek] - (int)FirstDayOfWeek;
_selectionStart = hit.AddDays(-preDays);
SelectionEnd = SelectionStart.AddDays(6);
}
/// <summary>
/// Selecs the work-week where the hit is contanied
/// </summary>
/// <param name="hit"></param>
private void SelectWorkWeek(DateTime hit)
{
int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[(int)hit.DayOfWeek] - (int)WorkWeekStart;
_selectionStart = hit.AddDays(-preDays);
SelectionEnd = SelectionStart.AddDays(Math.Abs(WorkWeekStart - WorkWeekEnd));
}
/// <summary>
/// Selecs the month where the hit is contanied
/// </summary>
/// <param name="hit"></param>
private void SelectMonth(DateTime hit)
{
_selectionStart = new DateTime(hit.Year, hit.Month, 1);
SelectionEnd = new DateTime(hit.Year, hit.Month, DateTime.DaysInMonth(hit.Year, hit.Month));
}
/// <summary>
/// Draws a box of text
/// </summary>
/// <param name="e"></param>
private void DrawBox(MonthViewBoxEventArgs e)
{
if (!e.BackgroundColor.IsEmpty)
{
using (SolidBrush b = new SolidBrush(e.BackgroundColor))
{
e.Graphics.FillRectangle(b, e.Bounds);
}
}
if (!e.TextColor.IsEmpty && !string.IsNullOrEmpty(e.Text))
{
TextRenderer.DrawText(e.Graphics, e.Text, e.Font != null ? e.Font : Font, e.Bounds, e.TextColor, e.TextFlags);
}
if (!e.BorderColor.IsEmpty)
{
using (Pen p = new Pen(e.BorderColor))
{
Rectangle r = e.Bounds;
r.Width--; r.Height--;
e.Graphics.DrawRectangle(p, r);
}
}
}
/// <summary>
/// Updates the size of the month.
/// </summary>
private void UpdateMonthSize()
{
//One row of day names plus 31 possible numbers
string[] strs = new string[7 + 31];
int maxWidth = 0;
int maxHeight = 0;
for (int i = 0; i < 7; i++)
{
strs[i] = ViewStart.AddDays(i).ToString(DayNamesFormat).Substring(0, DayNamesLength);
}
for (int i = 7; i < strs.Length; i++)
{
strs[i] = (i - 6).ToString();
}
Font f = new Font(Font, FontStyle.Bold);
for (int i = 0; i < strs.Length; i++)
{
Size s = TextRenderer.MeasureText(strs[i], f);
maxWidth = Math.Max(s.Width, maxWidth);
maxHeight = Math.Max(s.Height, maxHeight);
}
maxWidth += ItemPadding.Horizontal;
maxHeight += ItemPadding.Vertical;
_daySize = new Size(maxWidth, maxHeight);
_monthSize = new Size(maxWidth * 7, maxHeight * 7 + maxHeight * (DayNamesVisible ? 1 : 0));
}
/// <summary>
/// Updates the months.
/// </summary>
private void UpdateMonths()
{
int gapping = 2;
int calendarsX = Convert.ToInt32(Math.Max(Math.Floor((double)ClientSize.Width / (double)(MonthSize.Width + gapping)), 1.0));
int calendarsY = Convert.ToInt32(Math.Max(Math.Floor((double)ClientSize.Height / (double)(MonthSize.Height + gapping)), 1.0));
int calendars = calendarsX * calendarsY;
int monthsWidth = (calendarsX * MonthSize.Width) + (calendarsX - 1) * gapping;
int monthsHeight = (calendarsY * MonthSize.Height) + (calendarsY - 1) * gapping;
int startX = (ClientSize.Width - monthsWidth) / 2;
int startY = (ClientSize.Height - monthsHeight) / 2;
int curX = startX;
int curY = startY;
_forwardMonthIndex = calendarsX - 1;
_months = new MonthViewMonth[calendars];
for (int i = 0; i < Months.Length; i++)
{
Months[i] = new MonthViewMonth(this, ViewStart.AddMonths(i));
Months[i].SetLocation(new Point(curX, curY));
curX += gapping + MonthSize.Width;
if ((i + 1) % calendarsX == 0)
{
curX = startX;
curY += gapping + MonthSize.Height;
}
}
MonthViewMonth first = Months[0];
MonthViewMonth last = Months[_forwardMonthIndex];
SetBackwardButtonBounds(new Rectangle(first.Bounds.Left + ItemPadding.Left, first.Bounds.Top + ItemPadding.Top, DaySize.Height - ItemPadding.Horizontal, DaySize.Height - ItemPadding.Vertical));
SetForwardButtonBounds(new Rectangle(first.Bounds.Right - ItemPadding.Right - BackwardButtonBounds.Width, first.Bounds.Top + ItemPadding.Top, BackwardButtonBounds.Width, BackwardButtonBounds.Height ));
}
#endregion
#region Overrides
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.GotFocus"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
Invalidate();
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
Focus();
_mouseDown = true;
MonthViewDay day = HitTest(e.Location);
if (day != null)
{
switch (SelectionMode)
{
case MonthViewSelection.Manual:
case MonthViewSelection.Day:
SelectionEnd = _selectionStart = day.Date;
break;
case MonthViewSelection.WorkWeek:
SelectWorkWeek(day.Date);
break;
case MonthViewSelection.Week:
SelectWeek(day.Date);
break;
case MonthViewSelection.Month:
SelectMonth(day.Date);
break;
}
}
if (ForwardButtonSelected)
{
GoForward();
}
else if (BackwardButtonSelected)
{
GoBackward();
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (_mouseDown)
{
MonthViewDay day = HitTest(e.Location);
if (day != null && day != _lastHitted)
{
switch (SelectionMode)
{
case MonthViewSelection.Manual:
if (day.Date > SelectionStart)
{
SelectionEnd = day.Date;
}
else
{
SelectionStart = day.Date;
}
break;
case MonthViewSelection.Day:
SelectionEnd = _selectionStart = day.Date;
break;
case MonthViewSelection.WorkWeek:
SelectWorkWeek(day.Date);
break;
case MonthViewSelection.Week:
SelectWeek(day.Date);
break;
case MonthViewSelection.Month:
SelectMonth(day.Date);
break;
}
_lastHitted = day;
}
}
if (ForwardButtonBounds.Contains(e.Location))
{
SetForwardButtonSelected(true);
}
else if (ForwardButtonSelected)
{
SetForwardButtonSelected(false);
}
if (BackwardButtonBounds.Contains(e.Location))
{
SetBackwardButtonSelected(true);
}
else if (BackwardButtonSelected)
{
SetBackwardButtonSelected(false);
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
_mouseDown = false;
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
if (e.Delta < 0)
{
GoForward();
}
else
{
GoBackward();
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.LostFocus"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
Invalidate();
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.Clear(SystemColors.Window);
for (int i = 0; i < Months.Length; i++)
{
if (Months[i].Bounds.IntersectsWith(e.ClipRectangle))
{
#region MonthTitle
string title = Months[i].Date.ToString(MonthTitleFormat);
MonthViewBoxEventArgs evtTitle = new MonthViewBoxEventArgs(e.Graphics, Months[i].MonthNameBounds,
title,
Focused ? MonthTitleTextColor : MonthTitleTextColorInactive,
Focused ? MonthTitleColor : MonthTitleColorInactive);
DrawBox(evtTitle);
#endregion
#region DayNames
for (int j = 0; j < Months[i].DayNamesBounds.Length; j++)
{
MonthViewBoxEventArgs evtDay = new MonthViewBoxEventArgs(e.Graphics, Months[i].DayNamesBounds[j], Months[i].DayHeaders[j],
StringAlignment.Far, ForeColor, DayBackgroundColor);
DrawBox(evtDay);
}
if (Months[i].DayNamesBounds != null && Months[i].DayNamesBounds.Length != 0)
{
using (Pen p = new Pen(MonthTitleColor))
{
int y = Months[i].DayNamesBounds[0].Bottom;
e.Graphics.DrawLine(p, new Point(Months[i].Bounds.X, y), new Point(Months[i].Bounds.Right, y));
}
}
#endregion
#region Days
foreach (MonthViewDay day in Months[i].Days)
{
if (!day.Visible) continue;
MonthViewBoxEventArgs evtDay = new MonthViewBoxEventArgs(e.Graphics, day.Bounds, day.Date.Day.ToString(),
StringAlignment.Far,
day.Grayed ? DayGrayedText : (day.Selected ? DaySelectedTextColor : ForeColor),
day.Selected ? DaySelectedBackgroundColor : DayBackgroundColor);
if (day.Date.Equals(DateTime.Now.Date))
{
evtDay.BorderColor = TodayBorderColor;
}
DrawBox(evtDay);
}
#endregion
#region Arrows
if (i == 0)
{
Rectangle r = BackwardButtonBounds;
using (Brush b = new SolidBrush(BackwardButtonSelected ? ArrowsSelectedColor : ArrowsColor))
{
e.Graphics.FillPolygon(b, new Point[] {
new Point(r.Right, r.Top),
new Point(r.Right, r.Bottom - 1),
new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),
});
}
}
if (i == _forwardMonthIndex)
{
Rectangle r = ForwardButtonBounds;
using (Brush b = new SolidBrush(ForwardButtonSelected ? ArrowsSelectedColor : ArrowsColor))
{
e.Graphics.FillPolygon(b, new Point[] {
new Point(r.X, r.Top),
new Point(r.X, r.Bottom - 1),
new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),
});
}
}
#endregion
}
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Resize"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnResize(EventArgs e)
{
UpdateMonths();
Invalidate();
}
/// <summary>
/// Raises the <see cref="E:SelectionChanged"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void OnSelectionChanged(EventArgs e)
{
if (SelectionChanged != null)
{
SelectionChanged(this, e);
}
}
#endregion
}
}