/// <summary> /// Initializes a new instance of the <see cref="MonthCalendarMonth"/> class. /// </summary> /// <param name="monthCal">The <see cref="MonthCalendar"/> which hosts the <see cref="MonthCalendarMonth"/> instance.</param> /// <param name="date">The date that represents the month and year which is displayed in this instance.</param> public MonthCalendarMonth(MonthCalendar monthCal, DateTime date) { this.MonthCalendar = monthCal; this.Date = date; this.location = new Point(0, 0); MonthCalendarDate dt = new MonthCalendarDate(monthCal.CultureCalendar, date).FirstOfMonth.GetFirstDayInWeek(monthCal.FormatProvider); List <MonthCalendarDay> dayList = new List <MonthCalendarDay>(); List <MonthCalendarWeek> weekList = new List <MonthCalendarWeek>(); int dayAdjust = 0; while (dt.AddDays(dayAdjust).DayOfWeek != monthCal.FormatProvider.FirstDayOfWeek) { dayAdjust++; } int d = dayAdjust != 0 ? 8 - dayAdjust : 0; for (int i = dayAdjust; i < 42 + dayAdjust; i++, dt = dt.AddDays(1)) { MonthCalendarDay day = new MonthCalendarDay(this, dt.Date); dayList.Add(day); if (day.Visible) { if (this.firstVisibleDate == DateTime.MinValue) { this.firstVisibleDate = dt.Date; } if (!day.TrailingDate) { this.lastVisibleDate = dt.Date; } } if (i == dayAdjust || ((i - d) % 7) == 0) { DateTime weekEnd = dt.GetEndDateOfWeek(monthCal.FormatProvider).Date; int weekNumEnd = DateMethods.GetWeekOfYear(monthCal.Culture, monthCal.CultureCalendar, weekEnd); weekList.Add(new MonthCalendarWeek(this, weekNumEnd, dt.Date, weekEnd)); } if (dt.Date == monthCal.CultureCalendar.MaxSupportedDateTime.Date) { break; } } this.Days = dayList.ToArray(); this.Weeks = weekList.ToArray(); }
/// <summary> /// Initializes a new instance of the <see cref="MonthCalendarMonth"/> class. /// </summary> /// <param name="monthCal">The <see cref="MonthCalendar"/> which hosts the <see cref="MonthCalendarMonth"/> instance.</param> /// <param name="date">The date that represents the month and year which is displayed in this instance.</param> public MonthCalendarMonth(MonthCalendar monthCal, DateTime date) { this.MonthCalendar = monthCal; this.Date = date; this.location = new Point(0, 0); MonthCalendarDate dt = new MonthCalendarDate(monthCal.CultureCalendar, date).FirstOfMonth.GetFirstDayInWeek(monthCal.FormatProvider); List<MonthCalendarDay> dayList = new List<MonthCalendarDay>(); List<MonthCalendarWeek> weekList = new List<MonthCalendarWeek>(); int dayAdjust = 0; while (dt.AddDays(dayAdjust).DayOfWeek != monthCal.FormatProvider.FirstDayOfWeek) { dayAdjust++; } int d = dayAdjust != 0 ? 8 - dayAdjust : 0; for (int i = dayAdjust; i < 42 + dayAdjust; i++, dt = dt.AddDays(1)) { MonthCalendarDay day = new MonthCalendarDay(this, dt.Date); dayList.Add(day); if (day.Visible) { if (this.firstVisibleDate == DateTime.MinValue) { this.firstVisibleDate = dt.Date; } if (!day.TrailingDate) { this.lastVisibleDate = dt.Date; } } if (i == dayAdjust || ((i - d) % 7) == 0) { DateTime weekEnd = dt.GetEndDateOfWeek(monthCal.FormatProvider).Date; int weekNumEnd = DateMethods.GetWeekOfYear(monthCal.Culture, monthCal.CultureCalendar, weekEnd); weekList.Add(new MonthCalendarWeek(this, weekNumEnd, dt.Date, weekEnd)); } if (dt.Date == monthCal.CultureCalendar.MaxSupportedDateTime.Date) { break; } } this.Days = dayList.ToArray(); this.Weeks = weekList.ToArray(); }
/// <summary> /// Gets the first day in the week. /// </summary> /// <param name="provider">The format provider.</param> /// <returns>The first day in the week specified by this instance.</returns> public MonthCalendarDate GetFirstDayInWeek(ICustomFormatProvider provider) { DayOfWeek firstDayOfWeek = provider.FirstDayOfWeek; MonthCalendarDate dt = (MonthCalendarDate)this.Clone(); while (dt.DayOfWeek != firstDayOfWeek && dt.Date > this.calendar.MinSupportedDateTime) { dt = dt.AddDays(-1); } return(dt); }
/// <summary> /// Processes a dialog key. /// </summary> /// <param name="keyData">One of the <see cref="System.Windows.Forms.Keys"/> values that represents the key to process.</param> /// <returns>true if the key was processed by the control; otherwise, false.</returns> protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Left || keyData == Keys.Right) { this.SetDatePart(keyData == Keys.Left ? this.RightToLeft == RightToLeft.No : this.RightToLeft == RightToLeft.Yes); return true; } Calendar cal = this.datePicker.Picker.CultureCalendar; MonthCalendarDate dt = new MonthCalendarDate(cal, this.currentDate); DateTime date = this.Date; if (keyData == Keys.Up || keyData == Keys.Down) { bool up = keyData == Keys.Up; switch (this.selectedPart) { case SelectedDatePart.Day: { int day = dt.Day + (up ? 1 : -1); int daysInMonth = DateMethods.GetDaysInMonth(dt); if (day > daysInMonth) { day = 1; } else if (day < 1) { day = daysInMonth; } date = new DateTime(dt.Year, dt.Month, day, cal); break; } case SelectedDatePart.Month: { int day = dt.Day; int month = dt.Month + (up ? 1 : -1); int monthsInYear = cal.GetMonthsInYear(dt.Year); if (month > monthsInYear) { month = 1; } else if (month < 1) { month = monthsInYear; } DateTime newDate = new DateTime(dt.Year, month, 1, cal); dt = new MonthCalendarDate(cal, newDate); int daysInMonth = DateMethods.GetDaysInMonth(dt); newDate = daysInMonth < day ? cal.AddDays(newDate, daysInMonth - 1) : cal.AddDays(newDate, day - 1); date = newDate; break; } case SelectedDatePart.Year: { int year = dt.Year + (up ? 1 : -1); int minYear = cal.GetYear(this.MinDate); int maxYear = cal.GetYear(this.MaxDate); year = Math.Max(minYear, Math.Min(year, maxYear)); int yearDiff = year - dt.Year; date = cal.AddYears(this.currentDate, yearDiff); break; } } this.Date = date < this.MinDate ? this.MinDate : (date > this.MaxDate ? this.MaxDate : date); this.Refresh(); return true; } if (keyData == Keys.Home || keyData == Keys.End) { bool first = keyData == Keys.Home; switch (this.selectedPart) { case SelectedDatePart.Day: { date = first ? new DateTime(dt.Year, dt.Month, 1, cal) : new DateTime(dt.Year, dt.Month, DateMethods.GetDaysInMonth(dt), cal); break; } case SelectedDatePart.Month: { int day = dt.Day; date = first ? new DateTime(dt.Year, 1, 1, cal) : new DateTime(dt.Year, cal.GetMonthsInYear(dt.Year), 1, cal); int daysInMonth = DateMethods.GetDaysInMonth(dt); date = day > daysInMonth ? cal.AddDays(date, daysInMonth - 1) : cal.AddDays(date, day - 1); break; } case SelectedDatePart.Year: { date = first ? this.MinDate.Date : this.MaxDate.Date; break; } } this.Date = date < this.MinDate ? this.MinDate : (date > this.MaxDate ? this.MaxDate : date); this.Refresh(); return true; } if (keyData == Keys.Space && !this.inEditMode) { this.datePicker.SwitchPickerState(); return true; } return base.ProcessDialogKey(keyData); }
/// <summary> /// Gets the days in month for the specified date. /// </summary> /// <param name="date">The <see cref="MonthCalendarDate"/> to get the days in month for.</param> /// <returns>The number of days in the month.</returns> public static int GetDaysInMonth(MonthCalendarDate date) { return GetDaysInMonth(date.Calendar, date.Year, date.Month); }
/// <summary> /// Processes a dialog key. /// </summary> /// <param name="keyData">One of the <see cref="System.Windows.Forms.Keys"/> values that represents the key to process.</param> /// <returns>true if the key was processed by the control; otherwise, false.</returns> protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Left || keyData == Keys.Right) { this.SetDatePart(keyData == Keys.Left ? this.RightToLeft == RightToLeft.No : this.RightToLeft == RightToLeft.Yes); return(true); } Calendar cal = this.datePicker.Picker.CultureCalendar; MonthCalendarDate dt = new MonthCalendarDate(cal, this.currentDate); DateTime date = this.Date; if (keyData == Keys.Up || keyData == Keys.Down) { bool up = keyData == Keys.Up; switch (this.selectedPart) { case SelectedDatePart.Day: { int day = dt.Day + (up ? 1 : -1); int daysInMonth = DateMethods.GetDaysInMonth(dt); if (day > daysInMonth) { day = 1; } else if (day < 1) { day = daysInMonth; } date = new DateTime(dt.Year, dt.Month, day, cal); break; } case SelectedDatePart.Month: { int day = dt.Day; int month = dt.Month + (up ? 1 : -1); int monthsInYear = cal.GetMonthsInYear(dt.Year); if (month > monthsInYear) { month = 1; } else if (month < 1) { month = monthsInYear; } DateTime newDate = new DateTime(dt.Year, month, 1, cal); dt = new MonthCalendarDate(cal, newDate); int daysInMonth = DateMethods.GetDaysInMonth(dt); newDate = daysInMonth < day?cal.AddDays(newDate, daysInMonth - 1) : cal.AddDays(newDate, day - 1); date = newDate; break; } case SelectedDatePart.Year: { int year = dt.Year + (up ? 1 : -1); int minYear = cal.GetYear(this.MinDate); int maxYear = cal.GetYear(this.MaxDate); year = Math.Max(minYear, Math.Min(year, maxYear)); int yearDiff = year - dt.Year; date = cal.AddYears(this.currentDate, yearDiff); break; } } this.Date = date < this.MinDate ? this.MinDate : (date > this.MaxDate ? this.MaxDate : date); this.Refresh(); return(true); } if (keyData == Keys.Home || keyData == Keys.End) { bool first = keyData == Keys.Home; switch (this.selectedPart) { case SelectedDatePart.Day: { date = first ? new DateTime(dt.Year, dt.Month, 1, cal) : new DateTime(dt.Year, dt.Month, DateMethods.GetDaysInMonth(dt), cal); break; } case SelectedDatePart.Month: { int day = dt.Day; date = first ? new DateTime(dt.Year, 1, 1, cal) : new DateTime(dt.Year, cal.GetMonthsInYear(dt.Year), 1, cal); int daysInMonth = DateMethods.GetDaysInMonth(dt); date = day > daysInMonth?cal.AddDays(date, daysInMonth - 1) : cal.AddDays(date, day - 1); break; } case SelectedDatePart.Year: { date = first ? this.MinDate.Date : this.MaxDate.Date; break; } } this.Date = date < this.MinDate ? this.MinDate : (date > this.MaxDate ? this.MaxDate : date); this.Refresh(); return(true); } if (keyData == Keys.Space && !this.inEditMode) { this.datePicker.SwitchPickerState(); return(true); } return(base.ProcessDialogKey(keyData)); }
/// <summary> /// Draws the header of a <see cref="MonthCalendarMonth"/>. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="calMonth">The <see cref="MonthCalendarMonth"/> to draw the header for.</param> /// <param name="state">The <see cref="MonthCalendarHeaderState"/>.</param> public override void DrawMonthHeader( Graphics g, MonthCalendarMonth calMonth, MonthCalendarHeaderState state) { if (calMonth == null || !CheckParams(g, calMonth.TitleBounds)) { return; } // get title bounds Rectangle rect = calMonth.TitleBounds; MonthCalendarDate date = new MonthCalendarDate(monthCal.CultureCalendar, calMonth.Date); MonthCalendarDate firstVisible = new MonthCalendarDate(monthCal.CultureCalendar, calMonth.FirstVisibleDate); string month; int year; // gets the month name for the month the MonthCalendarMonth represents and the year string if (firstVisible.Era != date.Era) { month = this.monthCal.FormatProvider.GetMonthName(firstVisible.Year, firstVisible.Month); year = firstVisible.Year; } else { month = this.monthCal.FormatProvider.GetMonthName(date.Year, date.Month); year = date.Year; } string yearString = this.monthCal.UseNativeDigits ? DateMethods.GetNativeNumberString(year, this.monthCal.Culture.NumberFormat.NativeDigits, false) : year.ToString(CultureInfo.CurrentUICulture); // get used font Font headerFont = this.monthCal.HeaderFont; // create bold font Font boldFont = new Font(headerFont.FontFamily, headerFont.SizeInPoints, FontStyle.Bold); // measure sizes SizeF monthSize = g.MeasureString(month, boldFont); SizeF yearSize = g.MeasureString(yearString, boldFont); float maxHeight = Math.Max(monthSize.Height, yearSize.Height); // calculates the width and the starting position of the arrows int width = (int)monthSize.Width + (int)yearSize.Width + 7; int arrowLeftX = rect.X + 6; int arrowRightX = rect.Right - 6; int arrowY = rect.Y + (rect.Height / 2) - 4; int x = Math.Max(0, rect.X + (rect.Width / 2) + 1 - (width / 2)); int y = Math.Max( 0, rect.Y + (rect.Height / 2) + 1 - (((int)maxHeight + 1) / 2)); // set the title month name bounds calMonth.TitleMonthBounds = new Rectangle( x, y, (int)monthSize.Width + 1, (int)maxHeight + 1); // set the title year bounds calMonth.TitleYearBounds = new Rectangle( x + calMonth.TitleMonthBounds.Width + 7, y, (int)yearSize.Width + 1, (int)maxHeight + 1); // generate points for the left and right arrow Point[] arrowLeft = new[] { new Point(arrowLeftX, arrowY + 4), new Point(arrowLeftX + 4, arrowY), new Point(arrowLeftX + 4, arrowY + 8), new Point(arrowLeftX, arrowY + 4) }; Point[] arrowRight = new[] { new Point(arrowRightX, arrowY + 4), new Point(arrowRightX - 4, arrowY), new Point(arrowRightX - 4, arrowY + 8), new Point(arrowRightX, arrowY + 4) }; // get color table MonthCalendarColorTable colorTable = this.ColorTable; // get brushes for normal, mouse over and selected state using (SolidBrush brush = new SolidBrush(colorTable.HeaderText), brushOver = new SolidBrush(colorTable.HeaderActiveText), brushSelected = new SolidBrush(colorTable.HeaderSelectedText)) { // get title month name and year bounds Rectangle monthRect = calMonth.TitleMonthBounds; Rectangle yearRect = calMonth.TitleYearBounds; // set used fonts Font monthFont = headerFont; Font yearFont = headerFont; // set used brushes SolidBrush monthBrush = brush, yearBrush = brush; // adjust brush and font if year selected if (state == MonthCalendarHeaderState.YearSelected) { yearBrush = brushSelected; yearFont = boldFont; yearRect.Width += 4; } else if (state == MonthCalendarHeaderState.YearActive) { // adjust brush if mouse over year yearBrush = brushOver; } // adjust brush and font if month name is selected if (state == MonthCalendarHeaderState.MonthNameSelected) { monthBrush = brushSelected; monthFont = boldFont; monthRect.Width += 4; } else if (state == MonthCalendarHeaderState.MonthNameActive) { // adjust brush if mouse over month name monthBrush = brushOver; } // draws the month name and year string g.DrawString(month, monthFont, monthBrush, monthRect); g.DrawString(yearString, yearFont, yearBrush, yearRect); } boldFont.Dispose(); // if left arrow has to be drawn //if (calMonth.DrawLeftButton) //{ // // get arrow color // Color arrowColor = this.monthCal.LeftButtonState == ButtonState.Normal ? // GetGrayColor(this.monthCal.Enabled, colorTable.HeaderArrow) : colorTable.HeaderActiveArrow; // // set left arrow rect // this.monthCal.SetLeftArrowRect(new Rectangle(rect.X, rect.Y, 15, rect.Height)); // // draw left arrow // using (GraphicsPath path = new GraphicsPath()) // { // path.AddLines(arrowLeft); // using (SolidBrush brush = new SolidBrush(arrowColor)) // { // g.FillPath(brush, path); // } // using (Pen p = new Pen(arrowColor)) // { // g.DrawPath(p, path); // } // } //} // if right arrow has to be drawn // if (calMonth.DrawRightButton) // { // // get arrow color // Color arrowColor = this.monthCal.RightButtonState == ButtonState.Normal ? // GetGrayColor(this.monthCal.Enabled, colorTable.HeaderArrow) : colorTable.HeaderActiveArrow; // // set right arrow rect // this.monthCal.SetRightArrowRect(new Rectangle(rect.Right - 15, rect.Y, 15, rect.Height)); // // draw arrow // using (GraphicsPath path = new GraphicsPath()) // { // path.AddLines(arrowRight); // using (SolidBrush brush = new SolidBrush(arrowColor)) // { // g.FillPath(brush, path); // } // using (Pen p = new Pen(arrowColor)) // { // g.DrawPath(p, path); // } // } // } }
/// <summary> /// Draws a day in the month body of the calendar control. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="day">The <see cref="MonthCalendarDay"/> to draw.</param> public override void DrawDay(Graphics g, MonthCalendarDay day) { if (!CheckParams(g, day.Bounds)) { return; } // get color table MonthCalendarColorTable colors = this.ColorTable; // get the bounds of the day Rectangle rect = day.Bounds; var boldDate = this.monthCal.BoldedDatesCollection.Find(d => d.Value.Date == day.Date.Date); // if day is selected or in mouse over state if (day.MouseOver) { FillBackground( g, rect, colors.DayActiveGradientBegin, colors.DayActiveGradientEnd, colors.DayActiveGradientMode); } else if (day.Selected) { this.FillBackgroundInternal( g, rect, colors.DaySelectedGradientBegin, colors.DaySelectedGradientEnd, colors.DaySelectedGradientMode); } else if (!boldDate.IsEmpty && boldDate.Category.BackColorStart != Color.Empty && boldDate.Category.BackColorStart != Color.Transparent) { FillBackground( g, rect, boldDate.Category.BackColorStart, boldDate.Category.BackColorEnd.IsEmpty || boldDate.Category.BackColorEnd == Color.Transparent ? boldDate.Category.BackColorStart : boldDate.Category.BackColorEnd, boldDate.Category.GradientMode); } // get bolded dates List <DateTime> boldedDates = this.monthCal.GetBoldedDates(); bool bold = boldedDates.Contains(day.Date) || !boldDate.IsEmpty; // draw the day using (StringFormat format = GetStringAlignment(this.monthCal.DayTextAlignment)) { Color textColor = bold ? (boldDate.IsEmpty || boldDate.Category.ForeColor == Color.Empty || boldDate.Category.ForeColor == Color.Transparent ? colors.DayTextBold : boldDate.Category.ForeColor) : (day.Selected ? colors.DaySelectedText : (day.MouseOver ? colors.DayActiveText : (day.TrailingDate ? colors.DayTrailingText : colors.DayText))); using (SolidBrush brush = new SolidBrush(textColor)) { using (Font font = new Font( this.monthCal.Font.FontFamily, this.monthCal.Font.SizeInPoints, FontStyle.Bold)) { // adjust width Rectangle textRect = day.Bounds; textRect.Width -= 2; // determine if to use bold font //bool useBoldFont = day.Date == DateTime.Today || bold; bool useBoldFont = bold; var calDate = new MonthCalendarDate(monthCal.CultureCalendar, day.Date); string dayString = this.monthCal.UseNativeDigits ? DateMethods.GetNativeNumberString(calDate.Day, this.monthCal.Culture.NumberFormat.NativeDigits, false) : calDate.Day.ToString(this.monthCal.Culture); //if (!day.TrailingDate) //{ if (this.monthCal.Enabled) { g.DrawString( dayString, (useBoldFont ? font : this.monthCal.Font), brush, textRect, format); } else { ControlPaint.DrawStringDisabled( g, dayString, (useBoldFont ? font : this.monthCal.Font), Color.Transparent, textRect, format); } //} } } } // if today, draw border //if (day.Date == DateTime.Today) //{ // rect.Height -= 1; // rect.Width -= 2; // Color borderColor = day.Selected ? colors.DaySelectedTodayCircleBorder // : (day.MouseOver ? colors.DayActiveTodayCircleBorder : colors.DayTodayCircleBorder); // using (Pen p = new Pen(borderColor)) // { // g.DrawRectangle(p, rect); // rect.Offset(1, 0); // g.DrawRectangle(p, rect); // } //} }
/// <summary> /// Checks if the <paramref name="newSelectionDate"/> is within bounds of the <paramref name="baseDate"/> /// and the <see cref="MaxSelectionCount"/>. /// </summary> /// <param name="baseDate">The base date from where to check.</param> /// <param name="newSelectionDate">The new selection date.</param> /// <returns>A valid new selection date if valid parameters, otherwise <c>DateTime.MinValue</c>.</returns> private DateTime GetSelectionDate(DateTime baseDate, DateTime newSelectionDate) { if (this.maxSelectionCount == 0 || baseDate == DateTime.MinValue) { return newSelectionDate; } if (baseDate >= this.CultureCalendar.MinSupportedDateTime && newSelectionDate >= this.CultureCalendar.MinSupportedDateTime && baseDate <= this.CultureCalendar.MaxSupportedDateTime && newSelectionDate <= this.CultureCalendar.MaxSupportedDateTime) { int days = (baseDate - newSelectionDate).Days; if (Math.Abs(days) >= this.maxSelectionCount) { newSelectionDate = new MonthCalendarDate(this.CultureCalendar, baseDate).AddDays(days < 0 ? this.maxSelectionCount - 1 : 1 - this.maxSelectionCount).Date; } return newSelectionDate; } return DateTime.MinValue; }
/// <summary> /// Gets the days in month for the specified date. /// </summary> /// <param name="date">The <see cref="MonthCalendarDate"/> to get the days in month for.</param> /// <returns>The number of days in the month.</returns> public static int GetDaysInMonth(MonthCalendarDate date) { return(GetDaysInMonth(date.Calendar, date.Year, date.Month)); }
/// <summary> /// Draws the header of a <see cref="MonthCalendarMonth"/>. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="calMonth">The <see cref="MonthCalendarMonth"/> to draw the header for.</param> /// <param name="state">The <see cref="MonthCalendarHeaderState"/>.</param> public override void DrawMonthHeader( Graphics g, MonthCalendarMonth calMonth, MonthCalendarHeaderState state) { if (calMonth == null || !CheckParams(g, calMonth.TitleBounds)) { return; } // get title bounds Rectangle rect = calMonth.TitleBounds; MonthCalendarDate date = new MonthCalendarDate(monthCal.CultureCalendar, calMonth.Date); MonthCalendarDate firstVisible = new MonthCalendarDate(monthCal.CultureCalendar, calMonth.FirstVisibleDate); string month; int year; // gets the month name for the month the MonthCalendarMonth represents and the year string if (firstVisible.Era != date.Era) { month = this.monthCal.FormatProvider.GetMonthName(firstVisible.Year, firstVisible.Month); year = firstVisible.Year; } else { month = this.monthCal.FormatProvider.GetMonthName(date.Year, date.Month); year = date.Year; } string yearString = this.monthCal.UseNativeDigits ? DateMethods.GetNativeNumberString(year, this.monthCal.Culture.NumberFormat.NativeDigits, false) : year.ToString(CultureInfo.CurrentUICulture); // get used font Font headerFont = this.monthCal.HeaderFont; // create bold font Font boldFont = new Font(headerFont.FontFamily, headerFont.SizeInPoints, FontStyle.Bold); // measure sizes SizeF monthSize = g.MeasureString(month, boldFont); SizeF yearSize = g.MeasureString(yearString, boldFont); float maxHeight = Math.Max(monthSize.Height, yearSize.Height); // calculates the width and the starting position of the arrows int width = (int)monthSize.Width + (int)yearSize.Width + 7; int arrowLeftX = rect.X + 6; int arrowRightX = rect.Right - 6; int arrowY = rect.Y + (rect.Height / 2) - 4; int x = Math.Max(0, rect.X + (rect.Width / 2) + 1 - (width / 2)); int y = Math.Max( 0, rect.Y + (rect.Height / 2) + 1 - (((int)maxHeight + 1) / 2)); // set the title month name bounds calMonth.TitleMonthBounds = new Rectangle( x, y, (int)monthSize.Width + 1, (int)maxHeight + 1); // set the title year bounds calMonth.TitleYearBounds = new Rectangle( x + calMonth.TitleMonthBounds.Width + 7, y, (int)yearSize.Width + 1, (int)maxHeight + 1); // generate points for the left and right arrow Point[] arrowLeft = new[] { new Point(arrowLeftX, arrowY + 4), new Point(arrowLeftX + 4, arrowY), new Point(arrowLeftX + 4, arrowY + 8), new Point(arrowLeftX, arrowY + 4) }; Point[] arrowRight = new[] { new Point(arrowRightX, arrowY + 4), new Point(arrowRightX - 4, arrowY), new Point(arrowRightX - 4, arrowY + 8), new Point(arrowRightX, arrowY + 4) }; // get color table MonthCalendarColorTable colorTable = this.ColorTable; // get brushes for normal, mouse over and selected state using (SolidBrush brush = new SolidBrush(colorTable.HeaderText), brushOver = new SolidBrush(colorTable.HeaderActiveText), brushSelected = new SolidBrush(colorTable.HeaderSelectedText)) { // get title month name and year bounds Rectangle monthRect = calMonth.TitleMonthBounds; Rectangle yearRect = calMonth.TitleYearBounds; // set used fonts Font monthFont = headerFont; Font yearFont = headerFont; // set used brushes SolidBrush monthBrush = brush, yearBrush = brush; // adjust brush and font if year selected if (state == MonthCalendarHeaderState.YearSelected) { yearBrush = brushSelected; yearFont = boldFont; yearRect.Width += 4; } else if (state == MonthCalendarHeaderState.YearActive) { // adjust brush if mouse over year yearBrush = brushOver; } // adjust brush and font if month name is selected if (state == MonthCalendarHeaderState.MonthNameSelected) { monthBrush = brushSelected; monthFont = boldFont; monthRect.Width += 4; } else if (state == MonthCalendarHeaderState.MonthNameActive) { // adjust brush if mouse over month name monthBrush = brushOver; } // draws the month name and year string g.DrawString(month, monthFont, monthBrush, monthRect); g.DrawString(yearString, yearFont, yearBrush, yearRect); } boldFont.Dispose(); // if left arrow has to be drawn if (calMonth.DrawLeftButton) { // get arrow color Color arrowColor = this.monthCal.LeftButtonState == ButtonState.Normal ? GetGrayColor(this.monthCal.Enabled, colorTable.HeaderArrow) : colorTable.HeaderActiveArrow; // set left arrow rect this.monthCal.SetLeftArrowRect(new Rectangle(rect.X, rect.Y, 15, rect.Height)); // draw left arrow using (GraphicsPath path = new GraphicsPath()) { path.AddLines(arrowLeft); using (SolidBrush brush = new SolidBrush(arrowColor)) { g.FillPath(brush, path); } using (Pen p = new Pen(arrowColor)) { g.DrawPath(p, path); } } } // if right arrow has to be drawn if (calMonth.DrawRightButton) { // get arrow color Color arrowColor = this.monthCal.RightButtonState == ButtonState.Normal ? GetGrayColor(this.monthCal.Enabled, colorTable.HeaderArrow) : colorTable.HeaderActiveArrow; // set right arrow rect this.monthCal.SetRightArrowRect(new Rectangle(rect.Right - 15, rect.Y, 15, rect.Height)); // draw arrow using (GraphicsPath path = new GraphicsPath()) { path.AddLines(arrowRight); using (SolidBrush brush = new SolidBrush(arrowColor)) { g.FillPath(brush, path); } using (Pen p = new Pen(arrowColor)) { g.DrawPath(p, path); } } } }
/// <summary> /// Draws the footer. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="rect">The <see cref="Rectangle"/> to draw in.</param> /// <param name="active">true if the footer is in mouse over state; otherwise false.</param> public override void DrawFooter(Graphics g, Rectangle rect, bool active) { if (!CheckParams(g, rect)) { return; } string dateString = new MonthCalendarDate(this.monthCal.CultureCalendar, DateTime.Today).ToString( null, null, this.monthCal.FormatProvider, this.monthCal.UseNativeDigits ? this.monthCal.Culture.NumberFormat.NativeDigits : null); // get date size SizeF dateSize = g.MeasureString(dateString, this.monthCal.FooterFont); // get today rectangle and adjust position Rectangle todayRect = rect; todayRect.X += 2; // if in RTL mode, adjust position if (this.monthCal.UseRTL) { todayRect.X = rect.Right - 20; } // adjust bounds of today rectangle todayRect.Y = rect.Y + (rect.Height / 2) - 5; todayRect.Height = 11; todayRect.Width = 18; // draw the today rectangle using (Pen p = new Pen(this.ColorTable.FooterTodayCircleBorder)) { g.DrawRectangle(p, todayRect); } // get top position to draw the text at int y = rect.Y + (rect.Height / 2) - ((int)dateSize.Height / 2); Rectangle dateRect; // if in RTL mode if (this.monthCal.UseRTL) { // get date bounds dateRect = new Rectangle( rect.X + 1, y, todayRect.Left - rect.X, (int)dateSize.Height + 1); } else { // get date bounds dateRect = new Rectangle( todayRect.Right + 2, y, rect.Width - todayRect.Width, (int)dateSize.Height + 1); } // draw date string using (StringFormat format = GetStringAlignment(this.monthCal.UseRTL ? ContentAlignment.MiddleRight : ContentAlignment.MiddleLeft)) { using (SolidBrush brush = new SolidBrush(active ? this.ColorTable.FooterActiveText : GetGrayColor(this.monthCal.Enabled, this.ColorTable.FooterText))) { g.DrawString(dateString, this.monthCal.FooterFont, brush, dateRect, format); } } }
/// <summary> /// Draws a day in the month body of the calendar control. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="day">The <see cref="MonthCalendarDay"/> to draw.</param> public override void DrawDay(Graphics g, MonthCalendarDay day) { if (!CheckParams(g, day.Bounds)) { return; } // get color table MonthCalendarColorTable colors = this.ColorTable; // get the bounds of the day Rectangle rect = day.Bounds; var boldDate = this.monthCal.BoldedDatesCollection.Find(d => d.Value.Date == day.Date.Date); // if day is selected or in mouse over state if (day.MouseOver) { FillBackground( g, rect, colors.DayActiveGradientBegin, colors.DayActiveGradientEnd, colors.DayActiveGradientMode); } else if (day.Selected) { this.FillBackgroundInternal( g, rect, colors.DaySelectedGradientBegin, colors.DaySelectedGradientEnd, colors.DaySelectedGradientMode); } else if (!boldDate.IsEmpty && boldDate.Category.BackColorStart != Color.Empty && boldDate.Category.BackColorStart != Color.Transparent) { FillBackground( g, rect, boldDate.Category.BackColorStart, boldDate.Category.BackColorEnd.IsEmpty || boldDate.Category.BackColorEnd == Color.Transparent ? boldDate.Category.BackColorStart : boldDate.Category.BackColorEnd, boldDate.Category.GradientMode); } // get bolded dates List<DateTime> boldedDates = this.monthCal.GetBoldedDates(); bool bold = boldedDates.Contains(day.Date) || !boldDate.IsEmpty; // draw the day using (StringFormat format = GetStringAlignment(this.monthCal.DayTextAlignment)) { Color textColor = bold ? (boldDate.IsEmpty || boldDate.Category.ForeColor == Color.Empty || boldDate.Category.ForeColor == Color.Transparent ? colors.DayTextBold : boldDate.Category.ForeColor) : (day.Selected ? colors.DaySelectedText : (day.MouseOver ? colors.DayActiveText : (day.TrailingDate ? colors.DayTrailingText : colors.DayText))); using (SolidBrush brush = new SolidBrush(textColor)) { using (Font font = new Font( this.monthCal.Font.FontFamily, this.monthCal.Font.SizeInPoints, FontStyle.Bold)) { // adjust width Rectangle textRect = day.Bounds; textRect.Width -= 2; // determine if to use bold font bool useBoldFont = day.Date == DateTime.Today || bold; var calDate = new MonthCalendarDate(monthCal.CultureCalendar, day.Date); string dayString = this.monthCal.UseNativeDigits ? DateMethods.GetNativeNumberString(calDate.Day, this.monthCal.Culture.NumberFormat.NativeDigits, false) : calDate.Day.ToString(this.monthCal.Culture); if (this.monthCal.Enabled) { g.DrawString( dayString, (useBoldFont ? font : this.monthCal.Font), brush, textRect, format); } else { ControlPaint.DrawStringDisabled( g, dayString, (useBoldFont ? font : this.monthCal.Font), Color.Transparent, textRect, format); } } } } // if today, draw border if (day.Date == DateTime.Today) { rect.Height -= 1; rect.Width -= 2; Color borderColor = day.Selected ? colors.DaySelectedTodayCircleBorder : (day.MouseOver ? colors.DayActiveTodayCircleBorder : colors.DayTodayCircleBorder); using (Pen p = new Pen(borderColor)) { g.DrawRectangle(p, rect); rect.Offset(1, 0); g.DrawRectangle(p, rect); } } }
/// <summary> /// Calculates the proportions of this instance of <see cref="MonthCalendarMonth"/>. /// </summary> /// <param name="loc">The top left corner of the month.</param> private void CalculateProportions(Point loc) { // set title bounds this.TitleBounds = new Rectangle(loc, this.MonthCalendar.HeaderSize); // set helper variables bool useRTL = this.MonthCalendar.UseRTL; int adjustX = this.MonthCalendar.WeekNumberSize.Width; int dayWidth = this.MonthCalendar.DaySize.Width; int dayHeight = this.MonthCalendar.DaySize.Height; int weekRectAdjust = 0; // if RTL mode if (useRTL) { // set new values weekRectAdjust = dayWidth * 7; adjustX = 0; } // calculate day names header bounds this.DayNamesBounds = new Rectangle( new Point(loc.X + adjustX, loc.Y + this.TitleBounds.Height), this.MonthCalendar.DayNamesSize); // calculate week number header bounds Rectangle weekNumberRect = new Rectangle( loc.X + weekRectAdjust, loc.Y + this.TitleBounds.Height + this.DayNamesBounds.Height, this.MonthCalendar.WeekNumberSize.Width, dayHeight); // save week header bounds Rectangle weekBounds = weekNumberRect; // calculate month body bounds Rectangle monthRect = new Rectangle( loc.X + adjustX, loc.Y + this.TitleBounds.Height + this.DayNamesBounds.Height, dayWidth * 7, dayHeight * 6); // get start position at where to draw int startX = monthRect.X; adjustX = dayWidth; // if in RTL mode adjust start position and advancing width if (useRTL) { startX = monthRect.Right - dayWidth; adjustX = -dayWidth; } int x = startX; int y = monthRect.Y; int j = 0; if (this.Days.Length > 0 && new MonthCalendarDate(this.MonthCalendar.CultureCalendar, this.Days[0].Date).DayOfWeek != this.MonthCalendar.FormatProvider.FirstDayOfWeek) { DayOfWeek currentDayOfWeek = this.MonthCalendar.FormatProvider.FirstDayOfWeek; DayOfWeek dayOfWeek = new MonthCalendarDate(this.MonthCalendar.CultureCalendar, this.Days[0].Date).DayOfWeek; while (currentDayOfWeek != dayOfWeek) { x += adjustX; if ((j + 1) % 7 == 0) { x = startX; y += dayHeight; } int nextDay = (int)currentDayOfWeek + 1; if (nextDay > 6) { nextDay = 0; } currentDayOfWeek = (DayOfWeek)nextDay; j++; } } // loop through all possible 42 days for (int i = 0; i < this.Days.Length; i++, j++) { // set bounds of the day this.Days[i].Bounds = new Rectangle(x, y, dayWidth, dayHeight); // if at the beginning of a row if (i % 7 == 0) { // check if any day in the week is visible bool visible = this.Days[i].Visible || this.Days[Math.Min(i + 6, this.Days.Length - 1)].Visible; // set the week number header element bounds and if it's visible this.Weeks[i / 7].Bounds = weekNumberRect; this.Weeks[i / 7].Visible = visible; // adjust bounds of week header if (visible) { weekBounds = Rectangle.Union(weekBounds, weekNumberRect); } // adjust top position of the week number header bounds weekNumberRect.Y += dayHeight; } // adjust left position of the next day x += adjustX; // if last day in the row if ((j + 1) % 7 == 0) { // reset to start drawing position x = startX; // and advance a row y += dayHeight; } } // adjust the month body height and top position monthRect.Y = weekBounds.Y; monthRect.Height = weekBounds.Height; // set month body bounds this.MonthBounds = monthRect; // set week number header bounds this.WeekBounds = weekBounds; }
/// <summary> /// Processes a dialog key. /// </summary> /// <param name="keyData">One of the <see cref="Keys"/> value that represents the key to process.</param> /// <returns>true if the key was processed by the control; otherwise, false.</returns> protected override bool ProcessDialogKey(Keys keyData) { if (this.daySelectionMode != MonthCalendarSelectionMode.Day) { return base.ProcessDialogKey(keyData); } MonthCalendarDate dt = new MonthCalendarDate(this.cultureCalendar, this.selectionStart); bool retValue = false; if (keyData == Keys.Left) { this.selectionStart = dt.AddDays(-1).Date; retValue = true; } else if (keyData == Keys.Right) { this.selectionStart = dt.AddDays(1).Date; retValue = true; } else if (keyData == Keys.Up) { this.selectionStart = dt.AddDays(-7).Date; retValue = true; } else if (keyData == Keys.Down) { this.selectionStart = dt.AddDays(7).Date; retValue = true; } if (retValue) { if (this.selectionStart < this.minDate) { this.selectionStart = this.minDate; } else if (this.selectionStart > this.maxDate) { this.selectionStart = this.maxDate; } this.SetSelectionRange(this.daySelectionMode); this.EnsureSeletedDateIsVisible(); this.RaiseInternalDateSelected(); this.Invalidate(); return true; } return base.ProcessDialogKey(keyData); }
/// <summary> /// Gets the new date for the specified scroll direction. /// </summary> /// <param name="up">true for scrolling upwards, false otherwise.</param> /// <returns>The new start date.</returns> private DateTime GetNewScrollDate(bool up) { if ((this.lastVisibleDate == this.maxDate && !up) || (this.months[0].FirstVisibleDate == this.minDate && up)) { return this.viewStart; } MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, this.viewStart); int monthsToAdd = (this.scrollChange == 0 ? Math.Max((this.calendarDimensions.Width * this.calendarDimensions.Height) - 1, 1) : this.scrollChange) * (up ? -1 : 1); int length = this.months == null ? Math.Max(1, this.calendarDimensions.Width * this.calendarDimensions.Height) : this.months.Length; MonthCalendarDate newStartMonthDate = dt.AddMonths(monthsToAdd); MonthCalendarDate lastMonthDate = newStartMonthDate.AddMonths(length - 1); MonthCalendarDate lastMonthEndDate = lastMonthDate.AddDays(lastMonthDate.DaysInMonth - 1 - lastMonthDate.Day); if (newStartMonthDate.Date < this.minDate) { newStartMonthDate = new MonthCalendarDate(this.CultureCalendar, this.minDate); } else if (lastMonthEndDate.Date >= this.maxDate || lastMonthDate.Date >= this.maxDate) { MonthCalendarDate maxdt = new MonthCalendarDate(this.CultureCalendar, this.maxDate).FirstOfMonth; newStartMonthDate = maxdt.AddMonths(1 - length); } return newStartMonthDate.Date; }
/// <summary> /// Raises the <see cref="System.Windows.Forms.Control.MouseDown"/> event. /// </summary> /// <param name="e">A <see cref="MouseEventArgs"/> that contains the event data.</param> protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); this.Focus(); this.Capture = true; // reset the selection range where selection started this.selectionStartRange = null; if (e.Button == MouseButtons.Left) { // perform hit test MonthCalendarHitTest hit = this.HitTest(e.Location); // set current bounds this.currentMoveBounds = hit.Bounds; // set current hit type this.currentHitType = hit.Type; switch (hit.Type) { case MonthCalendarHitType.Day: { // save old selection range SelectionRange oldRange = this.SelectionRange; if (!this.extendSelection || this.daySelectionMode != MonthCalendarSelectionMode.Manual) { // clear all selection ranges this.selectionRanges.Clear(); } switch (this.daySelectionMode) { case MonthCalendarSelectionMode.Day: { this.OnDateClicked(new DateEventArgs(hit.Date)); // only single days are selectable if (this.selectionStart != hit.Date) { this.SelectionStart = hit.Date; this.RaiseDateSelected(); } break; } case MonthCalendarSelectionMode.WorkWeek: { // only single work week is selectable // get first day of week DateTime firstDay = new MonthCalendarDate(this.CultureCalendar, hit.Date).GetFirstDayInWeek(this.formatProvider).Date; // get work days List<DayOfWeek> workDays = DateMethods.GetWorkDays(this.nonWorkDays); // reset selection start and end this.selectionEnd = DateTime.MinValue; this.selectionStart = DateTime.MinValue; // current range SelectionRange currentRange = null; // build selection ranges for work days for (int i = 0; i < 7; i++) { DateTime toAdd = firstDay.AddDays(i); if (workDays.Contains(toAdd.DayOfWeek)) { if (currentRange == null) { currentRange = new SelectionRange(DateTime.MinValue, DateTime.MinValue); } if (currentRange.Start == DateTime.MinValue) { currentRange.Start = toAdd; } else { currentRange.End = toAdd; } } else if (currentRange != null) { this.selectionRanges.Add(currentRange); currentRange = null; } } if (this.selectionRanges.Count >= 1) { // set first selection range this.SelectionRange = this.selectionRanges[0]; this.selectionRanges.RemoveAt(0); // if selection range changed, raise event if (this.SelectionRange != oldRange) { this.RaiseDateSelected(); } } else { this.Refresh(); } break; } case MonthCalendarSelectionMode.FullWeek: { // only a full week is selectable // get selection start and end MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, hit.Date).GetFirstDayInWeek( this.formatProvider); this.selectionStart = dt.Date; this.selectionEnd = dt.GetEndDateOfWeek(this.formatProvider).Date; // if range changed, raise event if (this.SelectionRange != oldRange) { this.RaiseDateSelected(); this.Refresh(); } break; } case MonthCalendarSelectionMode.Month: { // only a full month is selectable MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, hit.Date).FirstOfMonth; // get selection start and end this.selectionStart = dt.Date; this.selectionEnd = dt.AddMonths(1).AddDays(-1).Date; // if range changed, raise event if (this.SelectionRange != oldRange) { this.RaiseDateSelected(); this.Refresh(); } break; } case MonthCalendarSelectionMode.Manual: { if (this.extendSelection) { var range = this.selectionRanges.Find(r => hit.Date >= r.Start && hit.Date <= r.End); if (range != null) { this.selectionRanges.Remove(range); } } // manual mode - selection ends when user is releasing the left mouse button this.selectionStarted = true; this.backupRange = this.SelectionRange; this.selectionEnd = DateTime.MinValue; this.SelectionStart = hit.Date; break; } } break; } case MonthCalendarHitType.Week: { this.selectionRanges.Clear(); if (this.maxSelectionCount > 6 || this.maxSelectionCount == 0) { this.backupRange = this.SelectionRange; this.selectionStarted = true; this.selectionEnd = new MonthCalendarDate(this.CultureCalendar, hit.Date).GetEndDateOfWeek(this.formatProvider).Date; this.SelectionStart = hit.Date; this.selectionStartRange = this.SelectionRange; } break; } case MonthCalendarHitType.MonthName: { this.monthSelected = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; this.Invalidate(hit.InvalidateBounds); this.Update(); this.monthMenu.Tag = hit.Date; this.UpdateMonthMenu(this.CultureCalendar.GetYear(hit.Date)); this.showingMenu = true; // show month menu this.monthMenu.Show(this, hit.Bounds.Right, e.Location.Y); break; } case MonthCalendarHitType.MonthYear: { this.yearSelected = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; this.Invalidate(hit.InvalidateBounds); this.Update(); this.UpdateYearMenu(this.CultureCalendar.GetYear(hit.Date)); this.yearMenu.Tag = hit.Date; this.showingMenu = true; // show year menu this.yearMenu.Show(this, hit.Bounds.Right, e.Location.Y); break; } case MonthCalendarHitType.Arrow: { // an arrow was pressed // set new start date if (this.SetStartDate(hit.Date)) { // update months this.UpdateMonths(); // raise event this.RaiseDateChanged(); this.mouseMoveFlags.HeaderDate = this.leftArrowRect.Contains(e.Location) ? this.months[0].Date : this.months[this.calendarDimensions.Width - 1].Date; this.Refresh(); } break; } case MonthCalendarHitType.Footer: { // footer was pressed this.selectionRanges.Clear(); bool raiseDateChanged = false; SelectionRange range = this.SelectionRange; // determine if date changed event has to be raised if (DateTime.Today < this.months[0].FirstVisibleDate || DateTime.Today > this.lastVisibleDate) { // set new start date if (this.SetStartDate(DateTime.Today)) { // update months this.UpdateMonths(); raiseDateChanged = true; } else { break; } } // set new selection start and end values this.selectionStart = DateTime.Today; this.selectionEnd = DateTime.Today; this.SetSelectionRange(this.daySelectionMode); this.OnDateClicked(new DateEventArgs(DateTime.Today)); // raise events if necessary if (range != this.SelectionRange) { this.RaiseDateSelected(); } if (raiseDateChanged) { this.RaiseDateChanged(); } this.Refresh(); break; } case MonthCalendarHitType.Header: { // header was pressed this.Invalidate(hit.Bounds); this.Update(); break; } } } }
/// <summary> /// Sets the selection range for the specified <see cref="MonthCalendarSelectionMode"/>. /// </summary> /// <param name="selMode">The <see cref="MonthCalendarSelectionMode"/> value to set the selection range for.</param> private void SetSelectionRange(MonthCalendarSelectionMode selMode) { switch (selMode) { case MonthCalendarSelectionMode.Day: { this.selectionEnd = this.selectionStart; break; } case MonthCalendarSelectionMode.WorkWeek: case MonthCalendarSelectionMode.FullWeek: { MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, this.selectionStart).GetFirstDayInWeek( this.formatProvider); this.selectionStart = dt.Date; this.selectionEnd = dt.AddDays(6).Date; break; } case MonthCalendarSelectionMode.Month: { MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, this.selectionStart).FirstOfMonth; this.selectionStart = dt.Date; this.selectionEnd = dt.AddMonths(1).AddDays(-1).Date; break; } } }
/// <summary> /// Raises the <see cref="System.Windows.Forms.Control.MouseMove"/> event. /// </summary> /// <param name="e">A <see cref="MouseEventArgs"/> that contains the event data.</param> protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Location == this.mouseLocation) { return; } this.mouseLocation = e.Location; // backup and reset mouse move flags this.mouseMoveFlags.BackupAndReset(); // perform hit test MonthCalendarHitTest hit = this.HitTest(e.Location); if (e.Button == MouseButtons.Left) { // if selection started - only in manual selection mode if (this.selectionStarted) { // if selection started with hit type Day and mouse is over new date if (hit.Type == MonthCalendarHitType.Day && this.currentHitType == MonthCalendarHitType.Day && this.currentMoveBounds != hit.Bounds) { this.currentMoveBounds = hit.Bounds; // set new selection end this.SelectionEnd = hit.Date; } else if (hit.Type == MonthCalendarHitType.Week && this.currentHitType == MonthCalendarHitType.Week) { // set indicator that a week header element is selected this.mouseMoveFlags.WeekHeader = true; // get new end date DateTime endDate = new MonthCalendarDate(this.CultureCalendar, hit.Date).AddDays(6).Date; // if new week header element if (this.currentMoveBounds != hit.Bounds) { this.currentMoveBounds = hit.Bounds; // check if selection is switched if (this.selectionStart == this.selectionStartRange.End) { // are we after the original end date? if (endDate > this.selectionStart) { // set original start date this.selectionStart = this.selectionStartRange.Start; // set new end date this.SelectionEnd = endDate; } else { // going backwards - set new "end" date - it's now the start date this.SelectionEnd = hit.Date; } } else { // we are after the start date if (endDate > this.selectionStart) { // set end date this.SelectionEnd = endDate; } else { // switch start and end this.selectionStart = this.selectionStartRange.End; this.SelectionEnd = hit.Date; } } } } } else { switch (hit.Type) { case MonthCalendarHitType.MonthName: { this.mouseMoveFlags.MonthName = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; this.Invalidate(hit.InvalidateBounds); break; } case MonthCalendarHitType.MonthYear: { this.mouseMoveFlags.Year = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; this.Invalidate(hit.InvalidateBounds); break; } case MonthCalendarHitType.Header: { this.mouseMoveFlags.HeaderDate = hit.Date; this.Invalidate(hit.InvalidateBounds); break; } case MonthCalendarHitType.Arrow: { bool useRTL = this.UseRTL; if (this.leftArrowRect.Contains(e.Location)) { this.mouseMoveFlags.LeftArrow = !useRTL; this.mouseMoveFlags.RightArrow = useRTL; this.mouseMoveFlags.HeaderDate = this.months[0].Date; } else { this.mouseMoveFlags.LeftArrow = useRTL; this.mouseMoveFlags.RightArrow = !useRTL; this.mouseMoveFlags.HeaderDate = this.months[this.calendarDimensions.Width - 1].Date; } this.Invalidate(hit.InvalidateBounds); break; } case MonthCalendarHitType.Footer: { this.mouseMoveFlags.Footer = true; this.Invalidate(hit.InvalidateBounds); break; } default: { this.Invalidate(); break; } } } } else if (e.Button == MouseButtons.None) { // no mouse button is pressed // set flags and invalidate corresponding region switch (hit.Type) { case MonthCalendarHitType.Day: { this.mouseMoveFlags.Day = hit.Date; var bold = this.GetBoldedDates().Contains(hit.Date) || this.boldDatesCollection.Exists(d => d.Value.Date == hit.Date.Date); this.OnActiveDateChanged(new ActiveDateChangedEventArgs(hit.Date, bold)); this.InvalidateMonth(hit.Date, true); break; } case MonthCalendarHitType.Week: { this.mouseMoveFlags.WeekHeader = true; break; } case MonthCalendarHitType.MonthName: { this.mouseMoveFlags.MonthName = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; break; } case MonthCalendarHitType.MonthYear: { this.mouseMoveFlags.Year = hit.Date; this.mouseMoveFlags.HeaderDate = hit.Date; break; } case MonthCalendarHitType.Header: { this.mouseMoveFlags.HeaderDate = hit.Date; break; } case MonthCalendarHitType.Arrow: { bool useRTL = this.UseRTL; if (this.leftArrowRect.Contains(e.Location)) { this.mouseMoveFlags.LeftArrow = !useRTL; this.mouseMoveFlags.RightArrow = useRTL; this.mouseMoveFlags.HeaderDate = this.months[0].Date; } else if (this.rightArrowRect.Contains(e.Location)) { this.mouseMoveFlags.LeftArrow = useRTL; this.mouseMoveFlags.RightArrow = !useRTL; this.mouseMoveFlags.HeaderDate = this.months[this.calendarDimensions.Width - 1].Date; } break; } case MonthCalendarHitType.Footer: { this.mouseMoveFlags.Footer = true; break; } } // if left arrow state changed if (this.mouseMoveFlags.LeftArrowChanged) { this.Invalidate(this.UseRTL ? this.rightArrowRect : this.leftArrowRect); this.Update(); } // if right arrow state changed if (this.mouseMoveFlags.RightArrowChanged) { this.Invalidate(this.UseRTL ? this.leftArrowRect : this.rightArrowRect); this.Update(); } // if header state changed if (this.mouseMoveFlags.HeaderDateChanged) { this.Invalidate(); } else if (this.mouseMoveFlags.MonthNameChanged || this.mouseMoveFlags.YearChanged) { // if state of month name or year in header changed SelectionRange range1 = new SelectionRange(this.mouseMoveFlags.MonthName, this.mouseMoveFlags.Backup.MonthName); SelectionRange range2 = new SelectionRange(this.mouseMoveFlags.Year, this.mouseMoveFlags.Backup.Year); this.Invalidate(this.months[this.GetIndex(range1.End)].TitleBounds); if (range1.End != range2.End) { this.Invalidate(this.months[this.GetIndex(range2.End)].TitleBounds); } } // if day state changed if (this.mouseMoveFlags.DayChanged) { // invalidate current day this.InvalidateMonth(this.mouseMoveFlags.Day, false); // invalidate last day this.InvalidateMonth(this.mouseMoveFlags.Backup.Day, false); } // if footer state changed if (this.mouseMoveFlags.FooterChanged) { this.Invalidate(this.footerRect); } } // if mouse is over a week header, change cursor if (this.mouseMoveFlags.WeekHeaderChanged) { this.Cursor = this.mouseMoveFlags.WeekHeader ? Cursors.UpArrow : Cursors.Default; } }
/// <summary> /// Draws the footer. /// </summary> /// <param name="g">The <see cref="Graphics"/> object used to draw.</param> /// <param name="rect">The <see cref="Rectangle"/> to draw in.</param> /// <param name="active">true if the footer is in mouse over state; otherwise false.</param> public override void DrawFooter(Graphics g, Rectangle rect, bool active) { if (!CheckParams(g, rect)) { return; } string dateString = new MonthCalendarDate(this.monthCal.CultureCalendar, DateTime.Today).ToString( null, null, this.monthCal.FormatProvider, this.monthCal.UseNativeDigits ? this.monthCal.Culture.NumberFormat.NativeDigits : null); // get date size SizeF dateSize = g.MeasureString(dateString, this.monthCal.FooterFont); // get today rectangle and adjust position Rectangle todayRect = rect; todayRect.X += 2; // if in RTL mode, adjust position if (this.monthCal.UseRTL) { todayRect.X = rect.Right - 20; } // adjust bounds of today rectangle todayRect.Y = rect.Y + (rect.Height / 2) - 5; todayRect.Height = 11; todayRect.Width = 18; // draw the today rectangle using (Pen p = new Pen(this.ColorTable.FooterTodayCircleBorder)) { g.DrawRectangle(p, todayRect); } // get top position to draw the text at int y = rect.Y + (rect.Height / 2) - ((int)dateSize.Height / 2); Rectangle dateRect; // if in RTL mode if (this.monthCal.UseRTL) { // get date bounds dateRect = new Rectangle( rect.X + 1, y, todayRect.Left - rect.X, (int)dateSize.Height + 1); } else { // get date bounds dateRect = new Rectangle( todayRect.Right + 2, y, rect.Width - todayRect.Width, (int)dateSize.Height + 1); } // draw date string using (StringFormat format = GetStringAlignment(this.monthCal.UseRTL ? ContentAlignment.MiddleRight : ContentAlignment.MiddleLeft)) { using (SolidBrush brush = new SolidBrush(active ? this.ColorTable.FooterActiveText : GetGrayColor(this.monthCal.Enabled, this.ColorTable.FooterText))) { g.DrawString(dateString, this.monthCal.FooterFont, brush, dateRect, format); } } }
/// <summary> /// Calculates the various sizes of a single month view and the global size of the control. /// </summary> private void CalculateSize(bool changeDimension) { // if already calculating - return if (this.inUpdate) { return; } this.inUpdate = true; using (Graphics g = this.CreateGraphics()) { // get sizes for different elements of the calendar SizeF daySize = g.MeasureString("30", this.Font); SizeF weekNumSize = g.MeasureString("59", this.Font); MonthCalendarDate date = new MonthCalendarDate(this.CultureCalendar, this.viewStart); SizeF monthNameSize = g.MeasureString( this.formatProvider.GetMonthName(date.Year, date.Month), this.headerFont); SizeF yearStringSize = g.MeasureString( this.viewStart.ToString("yyyy"), this.headerFont); SizeF footerStringSize = g.MeasureString( this.viewStart.ToShortDateString(), this.footerFont); // calculate the header height this.headerHeight = Math.Max( (int)Math.Max(monthNameSize.Height + 3, yearStringSize.Height) + 1, 15); // calculate the width of a single day this.dayWidth = Math.Max(12, (int)daySize.Width + 1) + 5; // calculate the height of a single day this.dayHeight = Math.Max(Math.Max(12, (int)weekNumSize.Height + 1), (int)daySize.Height + 1) + 2; // calculate the height of the footer this.footerHeight = Math.Max(12, (int)footerStringSize.Height + 1); // calculate the width of the week number header this.weekNumberWidth = this.showWeekHeader ? Math.Max(12, (int)weekNumSize.Width + 1) + 2 : 0; // set minimal height of the day name header this.dayNameHeight = 14; // loop through all day names foreach (string str in DateMethods.GetDayNames(this.formatProvider, this.useShortestDayNames ? 2 : 1)) { // get the size of the name SizeF dayNameSize = g.MeasureString(str, this.dayHeaderFont); // adjust the width of the day and the day name header height this.dayWidth = Math.Max(this.dayWidth, (int)dayNameSize.Width + 1); this.dayNameHeight = Math.Max( this.dayNameHeight, (int)dayNameSize.Height + 1); } // calculate the width and height of a MonthCalendarMonth element this.monthWidth = this.weekNumberWidth + (this.dayWidth * 7) + 1; this.monthHeight = this.headerHeight + this.dayNameHeight + (this.dayHeight * 6) + 1; if (changeDimension) { // calculate the dimension of the control int calWidthDim = Math.Max(1, this.Width / this.monthWidth); int calHeightDim = Math.Max(1, this.Height / this.monthHeight); // set the dimensions this.CalendarDimensions = new Size(calWidthDim, calHeightDim); } // set the width and height of the control this.Height = (this.monthHeight * this.calendarDimensions.Height) + (this.showFooter ? this.footerHeight : 0); this.Width = this.monthWidth * this.calendarDimensions.Width; // calculate the footer bounds this.footerRect = new Rectangle( 1, this.Height - this.footerHeight - 1, this.Width - 2, this.footerHeight); // update the months this.UpdateMonths(); } this.inUpdate = false; this.Refresh(); }
/// <summary> /// Calculates the proportions of this instance of <see cref="MonthCalendarMonth"/>. /// </summary> /// <param name="loc">The top left corner of the month.</param> private void CalculateProportions(Point loc) { // set title bounds this.TitleBounds = new Rectangle(loc, this.MonthCalendar.HeaderSize); // set helper variables bool useRTL = this.MonthCalendar.UseRTL; int adjustX = this.MonthCalendar.WeekNumberSize.Width; int dayWidth = this.MonthCalendar.DaySize.Width; int dayHeight = this.MonthCalendar.DaySize.Height; int weekRectAdjust = 0; // if RTL mode if (useRTL) { // set new values weekRectAdjust = dayWidth * 7; adjustX = 0; } // calculate day names header bounds this.DayNamesBounds = new Rectangle( new Point(loc.X + adjustX, loc.Y + this.TitleBounds.Height), this.MonthCalendar.DayNamesSize); // calculate week number header bounds Rectangle weekNumberRect = new Rectangle( loc.X + weekRectAdjust, loc.Y + this.TitleBounds.Height + this.DayNamesBounds.Height, this.MonthCalendar.WeekNumberSize.Width, dayHeight); // save week header bounds Rectangle weekBounds = weekNumberRect; // calculate month body bounds Rectangle monthRect = new Rectangle( loc.X + adjustX, loc.Y + this.TitleBounds.Height + this.DayNamesBounds.Height, dayWidth * 7, dayHeight * 6); // get start position at where to draw int startX = monthRect.X; adjustX = dayWidth; // if in RTL mode adjust start position and advancing width if (useRTL) { startX = monthRect.Right - dayWidth; adjustX = -dayWidth; } int x = startX; int y = monthRect.Y; int j = 0; if (this.Days.Length > 0 && new MonthCalendarDate(this.MonthCalendar.CultureCalendar, this.Days[0].Date).DayOfWeek != this.MonthCalendar.FormatProvider.FirstDayOfWeek) { DayOfWeek currentDayOfWeek = this.MonthCalendar.FormatProvider.FirstDayOfWeek; DayOfWeek dayOfWeek = new MonthCalendarDate(this.MonthCalendar.CultureCalendar, this.Days[0].Date).DayOfWeek; while (currentDayOfWeek != dayOfWeek) { x += adjustX; if ((j + 1) % 7 == 0) { x = startX; y += dayHeight; } int nextDay = (int)currentDayOfWeek + 1; if (nextDay > 6) { nextDay = 0; } currentDayOfWeek = (DayOfWeek)nextDay; j++; } } // loop through all possible 42 days for (int i = 0; i < this.Days.Length; i++, j++) { // set bounds of the day this.Days[i].Bounds = new Rectangle(x, y, dayWidth, dayHeight); // if at the beginning of a row if (i % 7 == 0) { // check if any day in the week is visible bool visible = this.Days[i].Visible || this.Days[Math.Min(i + 6, this.Days.Length - 1)].Visible; // set the week number header element bounds and if it's visible this.Weeks[i / 7].Bounds = weekNumberRect; this.Weeks[i / 7].Visible = visible; // adjust bounds of week header if (visible) { weekBounds = Rectangle.Union(weekBounds, weekNumberRect); } // adjust top position of the week number header bounds weekNumberRect.Y += dayHeight; } // adjust left position of the next day x += adjustX; // if last day in the row if ((j + 1) % 7 == 0) { // reset to start drawing position x = startX; // and advance a row y += dayHeight; } } // adjust the month body height and top position monthRect.Y = weekBounds.Y; monthRect.Height = weekBounds.Height; // set month body bounds this.MonthBounds = monthRect; // set week number header bounds this.WeekBounds = weekBounds; }
/// <summary> /// Sets the start date. /// </summary> /// <param name="start">The start date.</param> /// <returns>true if <paramref name="start"/> is valid; false otherwise.</returns> private bool SetStartDate(DateTime start) { if (start < DateTime.MinValue.Date || start > DateTime.MaxValue.Date) { return false; } DayOfWeek firstDayOfWeek = this.formatProvider.FirstDayOfWeek; MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, this.maxDate); if (start > this.maxDate) { start = dt.AddMonths(1 - this.months.Length).FirstOfMonth.Date; } if (start < this.minDate) { start = this.minDate; } dt = new MonthCalendarDate(this.CultureCalendar, start); int length = this.months != null ? this.months.Length - 1 : 0; while (dt.Date > this.minDate && dt.Day != 1) { dt = dt.AddDays(-1); } MonthCalendarDate endDate = dt.AddMonths(length); MonthCalendarDate endDateDay = endDate.AddDays(endDate.DaysInMonth - 1 - (endDate.Day - 1)); if (endDate.Date >= this.maxDate || endDateDay.Date >= this.maxDate) { dt = new MonthCalendarDate(this.CultureCalendar, this.maxDate).AddMonths(-length).FirstOfMonth; } this.viewStart = dt.Date; while (dt.Date > this.CultureCalendar.MinSupportedDateTime.Date && dt.DayOfWeek != firstDayOfWeek) { dt = dt.AddDays(-1); } this.realStart = dt.Date; return true; }
public string ParsePattern(MonthCalendarDate date, string[] nativeDigits = null) { // replace date separator with '/' string format = this.pattern.Replace(provider.DateSeparator, "/"); StringBuilder sb = new StringBuilder(); Calendar c = provider.Calendar; int i = 0; int index = 0; while (i < format.Length) { int tokLen; char ch = format[i]; string currentString; switch (ch) { case 'd': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = DateMethods.GetNumberString(date.Day, nativeDigits, tokLen == 2); this.isDayNumber = true; this.dayString = currentString; this.dayPartIndex = index++; this.dayIndex = sb.Length; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedDayName(c.GetDayOfWeek(date.Date)) : provider.GetDayName(c.GetDayOfWeek(date.Date)); this.dayNameString = currentString; } sb.Append(currentString); break; } case 'M': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = DateMethods.GetNumberString(date.Month, nativeDigits, tokLen == 2); this.isMonthNumber = true; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedMonthName(date.Year, date.Month) : provider.GetMonthName(date.Year, date.Month); } this.monthPartIndex = index++; this.monthIndex = sb.Length; this.monthString = currentString; sb.Append(currentString); break; } case 'y': { tokLen = CountChar(format, i, ch); var year = tokLen <= 2 ? date.Year % 100 : date.Year; currentString = DateMethods.GetNumberString(year, nativeDigits, tokLen <= 2); this.yearString = currentString; this.yearPartIndex = index++; this.yearIndex = sb.Length; sb.Append(currentString); break; } case 'g': { tokLen = CountChar(format, i, ch); currentString = provider.GetEraName(c.GetEra(date.Date)); this.eraString = currentString; sb.Append(currentString); break; } case '/': { tokLen = CountChar(format, i, ch); sb.Append(provider.DateSeparator); break; } default: { tokLen = 1; sb.Append(ch.ToString(CultureInfo.CurrentUICulture)); break; } } i += tokLen; } return(sb.ToString()); }
/// <summary> /// Updates the shown months. /// </summary> public void UpdateMonths() { int x = 0, y = 0, index = 0; int calWidthDim = this.calendarDimensions.Width; int calHeightDim = this.calendarDimensions.Height; List<MonthCalendarMonth> monthList = new List<MonthCalendarMonth>(); MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, this.viewStart); if (dt.GetEndDateOfWeek(this.formatProvider).Month != dt.Month) { dt = dt.GetEndDateOfWeek(this.formatProvider).FirstOfMonth; } if (this.UseRTL) { x = this.monthWidth * (calWidthDim - 1); for (int i = 0; i < calHeightDim; i++) { for (int j = calWidthDim - 1; j >= 0; j--) { if (dt.Date >= this.maxDate) { break; } monthList.Add(new MonthCalendarMonth(this, dt.Date) { Location = new Point(x, y), Index = index++ }); x -= this.monthWidth; dt = dt.AddMonths(1); } x = this.monthWidth * (calWidthDim - 1); y += this.monthHeight; } } else { for (int i = 0; i < calHeightDim; i++) { for (int j = 0; j < calWidthDim; j++) { if (dt.Date >= this.maxDate) { break; } monthList.Add(new MonthCalendarMonth(this, dt.Date) { Location = new Point(x, y), Index = index++ }); x += this.monthWidth; dt = dt.AddMonths(1); } x = 0; y += this.monthHeight; } } this.lastVisibleDate = monthList[monthList.Count - 1].LastVisibleDate; this.months = monthList.ToArray(); }
/// <summary> /// Raises the <see cref="System.Windows.Forms.Control.Paint"/> event. /// </summary> /// <param name="e">A <see cref="PaintEventArgs"/> that contains the event data.</param> protected override void OnPaint(PaintEventArgs e) { if (this.inEditMode) { e.Graphics.Clear(this.BackColor); base.OnPaint(e); return; } e.Graphics.Clear(this.Enabled ? (this.isValidDate ? this.BackColor : this.invalidDateBackColor) : SystemColors.Window); using (StringFormat format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.NoWrap)) { format.LineAlignment = StringAlignment.Center; if (this.RightToLeft == RightToLeft.Yes) { format.Alignment = StringAlignment.Far; } using (SolidBrush foreBrush = new SolidBrush(this.Enabled ? (this.isValidDate ? this.ForeColor : this.invalidDateForeColor) : SystemColors.GrayText), selectedBrush = new SolidBrush(SystemColors.HighlightText), selectedBack = new SolidBrush(SystemColors.Highlight)) { MonthCalendar cal = this.datePicker.Picker; ICustomFormatProvider provider = cal.FormatProvider; MonthCalendarDate date = new MonthCalendarDate(cal.CultureCalendar, this.currentDate); DatePatternParser parser = new DatePatternParser(provider.ShortDatePattern, provider); string dateString = parser.ParsePattern(date, this.datePicker.UseNativeDigits ? this.datePicker.Culture.NumberFormat.NativeDigits : null); this.dayPartIndex = parser.DayPartIndex; this.monthPartIndex = parser.MonthPartIndex; this.yearPartIndex = parser.YearPartIndex; List <CharacterRange> rangeList = new List <CharacterRange>(); int dayIndex = parser.DayIndex; int monthIndex = parser.MonthIndex; int yearIndex = parser.YearIndex; if (!string.IsNullOrEmpty(parser.DayString)) { rangeList.Add(new CharacterRange(dayIndex, parser.DayString.Length)); } if (!string.IsNullOrEmpty(parser.MonthString)) { rangeList.Add(new CharacterRange(monthIndex, parser.MonthString.Length)); } if (!string.IsNullOrEmpty(parser.YearString)) { rangeList.Add(new CharacterRange(yearIndex, parser.YearString.Length)); } format.SetMeasurableCharacterRanges(rangeList.ToArray()); Rectangle layoutRect = this.ClientRectangle; e.Graphics.DrawString(dateString, this.Font, foreBrush, layoutRect, format); Region[] dateRegions = e.Graphics.MeasureCharacterRanges(dateString, this.Font, layoutRect, format); this.dayBounds = dateRegions[0].GetBounds(e.Graphics); this.monthBounds = dateRegions[1].GetBounds(e.Graphics); this.yearBounds = dateRegions[2].GetBounds(e.Graphics); if (this.selectedPart == SelectedDatePart.Day) { e.Graphics.FillRectangle(selectedBack, this.dayBounds.X, this.dayBounds.Y - 2, this.dayBounds.Width + 1, this.dayBounds.Height + 1); e.Graphics.DrawString(parser.DayString, this.Font, selectedBrush, this.dayBounds.X - 2, this.dayBounds.Y - 2); } if (this.selectedPart == SelectedDatePart.Month) { e.Graphics.FillRectangle(selectedBack, this.monthBounds.X, this.monthBounds.Y - 2, this.monthBounds.Width + 1, this.monthBounds.Height + 1); e.Graphics.DrawString(parser.MonthString, this.Font, selectedBrush, this.monthBounds.X - 2, this.monthBounds.Y - 2); } if (this.selectedPart == SelectedDatePart.Year) { e.Graphics.FillRectangle(selectedBack, this.yearBounds.X, this.yearBounds.Y - 2, this.yearBounds.Width + 1, this.yearBounds.Height + 1); e.Graphics.DrawString(parser.YearString, this.Font, selectedBrush, this.yearBounds.X - 2, this.yearBounds.Y - 2); } } } base.OnPaint(e); }
/// <summary> /// Handles clicks in the month menu. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The event data.</param> private void MonthClick(object sender, EventArgs e) { MonthCalendarDate currentMonthYear = new MonthCalendarDate(this.CultureCalendar, (DateTime)this.monthMenu.Tag); int monthClicked = (int)((ToolStripMenuItem)sender).Tag; if (currentMonthYear.Month != monthClicked) { MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, new DateTime(currentMonthYear.Year, monthClicked, 1, this.CultureCalendar)); DateTime newStartDate = dt.AddMonths(-this.GetIndex(currentMonthYear.Date)).Date; if (this.SetStartDate(newStartDate)) { this.UpdateMonths(); this.RaiseDateChanged(); this.Focus(); this.Refresh(); } } }
public string ParsePattern(MonthCalendarDate date, string[] nativeDigits = null) { // replace date separator with '/' string format = this.pattern.Replace(provider.DateSeparator, "/"); StringBuilder sb = new StringBuilder(); Calendar c = provider.Calendar; int i = 0; int index = 0; while (i < format.Length) { int tokLen; char ch = format[i]; string currentString; switch (ch) { case 'd': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = DateMethods.GetNumberString(date.Day, nativeDigits, tokLen == 2); this.isDayNumber = true; this.dayString = currentString; this.dayPartIndex = index++; this.dayIndex = sb.Length; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedDayName(c.GetDayOfWeek(date.Date)) : provider.GetDayName(c.GetDayOfWeek(date.Date)); this.dayNameString = currentString; } sb.Append(currentString); break; } case 'M': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = DateMethods.GetNumberString(date.Month, nativeDigits, tokLen == 2); this.isMonthNumber = true; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedMonthName(date.Year, date.Month) : provider.GetMonthName(date.Year, date.Month); } this.monthPartIndex = index++; this.monthIndex = sb.Length; this.monthString = currentString; sb.Append(currentString); break; } case 'y': { tokLen = CountChar(format, i, ch); var year = tokLen <= 2 ? date.Year % 100 : date.Year; currentString = DateMethods.GetNumberString(year, nativeDigits, tokLen <= 2); this.yearString = currentString; this.yearPartIndex = index++; this.yearIndex = sb.Length; sb.Append(currentString); break; } case 'g': { tokLen = CountChar(format, i, ch); currentString = provider.GetEraName(c.GetEra(date.Date)); this.eraString = currentString; sb.Append(currentString); break; } case '/': { tokLen = CountChar(format, i, ch); sb.Append(provider.DateSeparator); break; } default: { tokLen = 1; sb.Append(ch.ToString(CultureInfo.CurrentUICulture)); break; } } i += tokLen; } return sb.ToString(); }
/// <summary> /// Handles clicks in the year menu. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The event data.</param> private void YearClick(object sender, EventArgs e) { DateTime currentMonthYear = (DateTime)this.yearMenu.Tag; int yearClicked = (int)((ToolStripMenuItem)sender).Tag; MonthCalendarDate dt = new MonthCalendarDate(this.CultureCalendar, currentMonthYear); if (dt.Year != yearClicked) { MonthCalendarDate newStartDate = new MonthCalendarDate(this.CultureCalendar, new DateTime(yearClicked, dt.Month, 1, this.CultureCalendar)) .AddMonths(-this.GetIndex(currentMonthYear)); if (this.SetStartDate(newStartDate.Date)) { this.UpdateMonths(); this.RaiseDateChanged(); this.Focus(); this.Refresh(); } } }
/// <summary> /// Raises the <see cref="System.Windows.Forms.Control.Paint"/> event. /// </summary> /// <param name="e">A <see cref="PaintEventArgs"/> that contains the event data.</param> protected override void OnPaint(PaintEventArgs e) { if (this.inEditMode) { e.Graphics.Clear(this.BackColor); base.OnPaint(e); return; } e.Graphics.Clear(this.Enabled ? (this.isValidDate ? this.BackColor : this.invalidDateBackColor) : SystemColors.Window); using (StringFormat format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.NoWrap)) { format.LineAlignment = StringAlignment.Center; if (this.RightToLeft == RightToLeft.Yes) { format.Alignment = StringAlignment.Far; } using (SolidBrush foreBrush = new SolidBrush(this.Enabled ? (this.isValidDate ? this.ForeColor : this.invalidDateForeColor) : SystemColors.GrayText), selectedBrush = new SolidBrush(SystemColors.HighlightText), selectedBack = new SolidBrush(SystemColors.Highlight)) { MonthCalendar cal = this.datePicker.Picker; ICustomFormatProvider provider = cal.FormatProvider; MonthCalendarDate date = new MonthCalendarDate(cal.CultureCalendar, this.currentDate); DatePatternParser parser = new DatePatternParser(provider.ShortDatePattern, provider); string dateString = parser.ParsePattern(date, this.datePicker.UseNativeDigits ? this.datePicker.Culture.NumberFormat.NativeDigits : null); this.dayPartIndex = parser.DayPartIndex; this.monthPartIndex = parser.MonthPartIndex; this.yearPartIndex = parser.YearPartIndex; List<CharacterRange> rangeList = new List<CharacterRange>(); int dayIndex = parser.DayIndex; int monthIndex = parser.MonthIndex; int yearIndex = parser.YearIndex; if (!string.IsNullOrEmpty(parser.DayString)) { rangeList.Add(new CharacterRange(dayIndex, parser.DayString.Length)); } if (!string.IsNullOrEmpty(parser.MonthString)) { rangeList.Add(new CharacterRange(monthIndex, parser.MonthString.Length)); } if (!string.IsNullOrEmpty(parser.YearString)) { rangeList.Add(new CharacterRange(yearIndex, parser.YearString.Length)); } format.SetMeasurableCharacterRanges(rangeList.ToArray()); Rectangle layoutRect = this.ClientRectangle; e.Graphics.DrawString(dateString, this.Font, foreBrush, layoutRect, format); Region[] dateRegions = e.Graphics.MeasureCharacterRanges(dateString, this.Font, layoutRect, format); this.dayBounds = dateRegions[0].GetBounds(e.Graphics); this.monthBounds = dateRegions[1].GetBounds(e.Graphics); this.yearBounds = dateRegions[2].GetBounds(e.Graphics); if (this.selectedPart == SelectedDatePart.Day) { e.Graphics.FillRectangle(selectedBack, this.dayBounds.X, this.dayBounds.Y - 2, this.dayBounds.Width + 1, this.dayBounds.Height + 1); e.Graphics.DrawString(parser.DayString, this.Font, selectedBrush, this.dayBounds.X - 2, this.dayBounds.Y - 2); } if (this.selectedPart == SelectedDatePart.Month) { e.Graphics.FillRectangle(selectedBack, this.monthBounds.X, this.monthBounds.Y - 2, this.monthBounds.Width + 1, this.monthBounds.Height + 1); e.Graphics.DrawString(parser.MonthString, this.Font, selectedBrush, this.monthBounds.X - 2, this.monthBounds.Y - 2); } if (this.selectedPart == SelectedDatePart.Year) { e.Graphics.FillRectangle(selectedBack, this.yearBounds.X, this.yearBounds.Y - 2, this.yearBounds.Width + 1, this.yearBounds.Height + 1); e.Graphics.DrawString(parser.YearString, this.Font, selectedBrush, this.yearBounds.X - 2, this.yearBounds.Y - 2); } } } base.OnPaint(e); }
public string ParsePattern(MonthCalendarDate date) { // replace date separator with '/' string format = pattern.Replace(provider.DateSeparator, "/"); // reverse pattern if rtl culture if (this.provider.IsRTLLanguage) { List <char> chars = new List <char>(format.ToCharArray()); chars.Reverse(); format = new string(chars.ToArray()); } StringBuilder sb = new StringBuilder(); Calendar c = provider.Calendar; int i = 0; int index = 0; while (i < format.Length) { int tokLen; char ch = format[i]; string currentString; switch (ch) { case 'd': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = tokLen == 2 ? date.Day.ToString("##00") : date.Day.ToString(); this.isDayNumber = true; this.dayString = currentString; this.dayPartIndex = index++; this.dayIndex = sb.Length; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedDayName(c.GetDayOfWeek(date.Date)) : provider.GetDayName(c.GetDayOfWeek(date.Date)); this.dayNameString = currentString; } sb.Append(currentString); break; } case 'M': { tokLen = CountChar(format, i, ch); if (tokLen <= 2) { currentString = tokLen == 2 ? date.Month.ToString("##00") : date.Month.ToString(); this.isMonthNumber = true; } else { currentString = tokLen == 3 ? provider.GetAbbreviatedMonthName(date.Year, date.Month) : provider.GetMonthName(date.Year, date.Month); } this.monthPartIndex = index++; this.monthIndex = sb.Length; this.monthString = currentString; sb.Append(currentString); break; } case 'y': { tokLen = CountChar(format, i, ch); currentString = tokLen <= 2 ? (date.Year % 100).ToString("##00") : date.Year.ToString(); this.yearString = currentString; this.yearPartIndex = index++; this.yearIndex = sb.Length; sb.Append(currentString); break; } case 'g': { tokLen = CountChar(format, i, ch); currentString = provider.GetEraName(c.GetEra(date.Date)); this.eraString = currentString; sb.Append(currentString); break; } case '/': { tokLen = CountChar(format, i, ch); sb.Append(provider.DateSeparator); break; } default: { tokLen = 1; sb.Append(ch.ToString()); break; } } i += tokLen; } return(sb.ToString()); }