/// <summary> /// The parse pattern. /// </summary> /// <param name="date"> /// The date. /// </param> /// <param name="nativeDigits"> /// The native digits. /// </param> /// <returns> /// The <see cref="string"/>. /// </returns> public string ParsePattern(MonthCalendarDate date, string[] nativeDigits = null) { // replace date separator with '/' string format = this._pattern.Replace(this._provider.DateSeparator, "/"); StringBuilder sb = new StringBuilder(); Calendar c = this._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 ? this._provider.GetAbbreviatedDayName(c.GetDayOfWeek(date.Date)) : this._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 ? this._provider.GetAbbreviatedMonthName(date.Year, date.Month) : this._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 = this._provider.GetEraName(c.GetEra(date.Date)); this.eraString = currentString; sb.Append(currentString); break; } case '/': { tokLen = CountChar(format, i, ch); sb.Append(this._provider.DateSeparator); break; } default: { tokLen = 1; sb.Append(ch.ToString(CultureInfo.CurrentUICulture)); break; } } i += tokLen; } return sb.ToString(); }
/// <summary> /// The draw month header. /// </summary> /// <param name="g"> /// The g. /// </param> /// <param name="calMonth"> /// The cal month. /// </param> /// <param name="state"> /// The state. /// </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(this._calendar.CultureCalendar, calMonth.Date); MonthCalendarDate firstVisible = new MonthCalendarDate(this._calendar.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._calendar.FormatProvider.GetMonthName(firstVisible.Year, firstVisible.Month); year = firstVisible.Year; } else { month = this._calendar.FormatProvider.GetMonthName(date.Year, date.Month); year = date.Year; } string yearString = this._calendar.UseNativeDigits ? DateMethods.GetNativeNumberString(year, this._calendar.Culture.NumberFormat.NativeDigits, false) : year.ToString(CultureInfo.CurrentUICulture); // get used font Font headerFont = this._calendar.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 Point(arrowLeftX, arrowY + 4), new Point(arrowLeftX + 4, arrowY), new Point(arrowLeftX + 4, arrowY + 8), new Point(arrowLeftX, arrowY + 4) }; Point[] arrowRight = { new Point(arrowRightX, arrowY + 4), new Point(arrowRightX - 4, arrowY), new Point(arrowRightX - 4, arrowY + 8), new Point(arrowRightX, arrowY + 4) }; // get brushes for normal, mouse over and selected RequestState // 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 Brush monthBrush = InactiveTextBrush, yearBrush = InactiveTextBrush; // adjust brush and font if year selected if (state == MonthCalendarHeaderState.YearSelected) { yearBrush = SelectedTextBrush; yearFont = boldFont; yearRect.Width += 4; } else if (state == MonthCalendarHeaderState.YearActive) { // adjust brush if mouse over year yearBrush = ActiveTextBrush; } // adjust brush and font if month name is selected if (state == MonthCalendarHeaderState.MonthNameSelected) { monthBrush = SelectedTextBrush; monthFont = boldFont; monthRect.Width += 4; } else if (state == MonthCalendarHeaderState.MonthNameActive) { // adjust brush if mouse over month name monthBrush = ActiveTextBrush; } // 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 var arrowBrush = this._calendar.LeftButtonState == ButtonState.Normal ? InactiveArrowBrush : ActiveArrowBrush; // set left arrow rect this._calendar.SetLeftArrowRect(new Rectangle(rect.X, rect.Y, 15, rect.Height)); // draw left arrow using (GraphicsPath path = new GraphicsPath()) { path.AddLines(arrowLeft); g.FillPath(arrowBrush, path); } } // if right arrow has to be drawn if (calMonth.DrawRightButton) { Brush arrowBrush = this._calendar.RightButtonState == ButtonState.Normal ? InactiveArrowBrush : ActiveArrowBrush; // set right arrow rect this._calendar.SetRightArrowRect(new Rectangle(rect.Right - 15, rect.Y, 15, rect.Height)); // draw arrow using (GraphicsPath path = new GraphicsPath()) { path.AddLines(arrowRight); g.FillPath(arrowBrush, path); } } }
/// <summary> /// The draw day. /// </summary> /// <param name="g"> /// The g. /// </param> /// <param name="day"> /// The day. /// </param> public override void DrawDay(Graphics g, MonthCalendarDay day) { if (!CheckParams(g, day.Bounds)) { return; } // if today, draw border if (day.Date == DateTime.Today) { this.DrawTodayLegend(g, day.Bounds); } // get the bounds of the day Rectangle rect = new Rectangle(day.Bounds.X + 2, day.Bounds.Y, day.Bounds.Width - 4, day.Bounds.Height); var boldDate = this._calendar.BoldedDatesCollection.Find(d => d.Value.Date == day.Date.Date); // if day is selected or in mouse over RequestState if (day.Selected) { g.FillRectangle(SelectedDayBackgroundBrush, rect); } else if (day.MouseOver) { g.FillRectangle(HoverDayBackgroundBrush, rect); } else if (!boldDate.IsEmpty && boldDate.Category.BackColorStart != Color.Empty && boldDate.Category.BackColorStart != Color.Transparent) { g.DrawRectangle(BorderPen, rect); } // get bolded dates List<DateTime> boldedDates = this._calendar.GetBoldedDates(); bool bold = boldedDates.Contains(day.Date) || !boldDate.IsEmpty; // draw the day using (StringFormat format = GetStringAlignment(this._calendar.DayTextAlignment)) { Color textColor = bold ? (boldDate.IsEmpty || boldDate.Category.ForeColor == Color.Empty || boldDate.Category.ForeColor == Color.Transparent ? InactiveTextColor : boldDate.Category.ForeColor) : (day.Selected ? SelectedDayTextColor : (day.MouseOver ? HoverDayTextColor : (day.TrailingDate ? TrailingDayColor : InactiveTextColor))); using (SolidBrush brush = new SolidBrush(textColor)) { using (Font font = new Font(this._calendar.Font.FontFamily, this._calendar.Font.SizeInPoints, FontStyle.Bold)) { // adjust width Rectangle textRect = day.Bounds; textRect.Width -= 2; // determine if to use bold font bool useBoldFont = day.Selected || bold; var calDate = new MonthCalendarDate(this._calendar.CultureCalendar, day.Date); string dayString = this._calendar.UseNativeDigits ? DateMethods.GetNativeNumberString( calDate.Day, this._calendar.Culture.NumberFormat.NativeDigits, false) : calDate.Day.ToString(this._calendar.Culture); if (this._calendar.Enabled) { g.DrawString(dayString, useBoldFont ? font : this._calendar.Font, brush, textRect, format); } else { ControlPaint.DrawStringDisabled( g, dayString, useBoldFont ? font : this._calendar.Font, Color.Transparent, textRect, format); } } } } }
/// <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._enhancedDatePicker.PickerCalendar.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._enhancedDatePicker.SwitchPickerState(); return true; } return base.ProcessDialogKey(keyData); }
/// <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)) { EnhancedMonthCalendar cal = this._enhancedDatePicker.PickerCalendar; ICustomFormatProvider provider = cal.FormatProvider; MonthCalendarDate date = new MonthCalendarDate(cal.CultureCalendar, this._currentDate); DatePatternParser parser = new DatePatternParser(provider.LongDatePattern, provider); string dateString = parser.ParsePattern( date, this._enhancedDatePicker.UseNativeDigits ? this._enhancedDatePicker.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> /// 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); }