// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace AntdUI { /// /// Calendar 日历 /// /// 按照日历形式展示数据的容器。 [Description("Calendar 日历")] [ToolboxItem(true)] [DefaultProperty("Date")] [DefaultEvent("DateChanged")] public class Calendar : IControl { public Calendar() { hover_lefts = new ITaskOpacity(this); hover_left = new ITaskOpacity(this); hover_rights = new ITaskOpacity(this); hover_right = new ITaskOpacity(this); hover_year = new ITaskOpacity(this); hover_month = new ITaskOpacity(this); hover_button = new ITaskOpacity(this); Date = DateNow; } #region 属性 int radius = 6; /// /// 圆角 /// [Description("圆角"), Category("外观"), DefaultValue(6)] public int Radius { get => radius; set { if (radius == value) return; radius = value; Invalidate(); } } bool full = false; /// /// 是否撑满 /// [Description("是否撑满"), Category("外观"), DefaultValue(false)] public bool Full { get => full; set { if (full == value) return; full = value; OnSizeChanged(EventArgs.Empty); Invalidate(); } } bool chinese = false; /// /// 显示农历 /// [Description("显示农历"), Category("外观"), DefaultValue(false)] public bool ShowChinese { get => chinese; set { if (chinese == value) return; chinese = value; OnSizeChanged(EventArgs.Empty); Invalidate(); } } bool showButtonToDay = true; /// /// 显示今天 /// [Description("显示今天"), Category("外观"), DefaultValue(true)] public bool ShowButtonToDay { get => showButtonToDay; set { if (showButtonToDay == value) return; showButtonToDay = value; OnSizeChanged(EventArgs.Empty); Invalidate(); } } Dictionary badge_list = new Dictionary(); /// /// 日期徽标回调 /// public Func?>? BadgeAction = null; #region 日期 List? calendar_year = null; List? calendar_month = null; List? calendar_day = null; DateTime _value = DateTime.Now; /// /// 控件当前日期 /// [Description("控件当前日期"), Category("数据")] public DateTime Value { get => _value; set { _value = value; DateChanged?.Invoke(this, new DateTimeEventArgs(_value)); Invalidate(); LoadBadge(); } } DateTime? minDate; /// /// 最小日期 /// [Description("最小日期"), Category("数据"), DefaultValue(null)] public DateTime? MinDate { get => minDate; set { if (minDate == value) return; minDate = value; Date = _Date; Invalidate(); } } DateTime? maxDate = null; /// /// 最大日期 /// [Description("最大日期"), Category("数据"), DefaultValue(null)] public DateTime? MaxDate { get => maxDate; set { if (maxDate == value) return; maxDate = value; Date = _Date; Invalidate(); } } DateTime _Date; DateTime DateNow = DateTime.Now; DateTime Date { get => _Date; set { _Date = value; calendar_day = GetCalendar(value); #region 添加月 var _calendar_month = new List(12); int x_m = 0, y_m = 0; for (int i = 0; i < 12; i++) { var d_m = new DateTime(value.Year, i + 1, 1); _calendar_month.Add(new Calendari(0, x_m, y_m, d_m.ToString("MM") + MonthButton, d_m, d_m.ToString("yyyy-MM"), minDate, maxDate)); x_m++; if (x_m > 2) { y_m++; x_m = 0; } } calendar_month = _calendar_month; #endregion #region 添加年 int syear = value.Year - 1; if (!value.Year.ToString().EndsWith("0")) { string temp = value.Year.ToString(); syear = int.Parse(temp.Substring(0, temp.Length - 1) + "0") - 1; } var _calendar_year = new List(12); int x_y = 0, y_y = 0; if (syear < 1) syear = 1; for (int i = 0; i < 12; i++) { var d_y = new DateTime(syear + i, value.Month, 1); _calendar_year.Add(new Calendari(i == 0 ? 0 : 1, x_y, y_y, d_y.ToString("yyyy"), d_y, d_y.ToString("yyyy"), minDate, maxDate)); x_y++; if (x_y > 2) { y_y++; x_y = 0; } } year_str = _calendar_year[1].date_str + "-" + _calendar_year[_calendar_year.Count - 2].date_str; calendar_year = _calendar_year; #endregion OnSizeChanged(EventArgs.Empty); LoadBadge(); hover_left.Enable = Helper.DateExceed(value.AddMonths(-1), minDate, maxDate); hover_right.Enable = Helper.DateExceed(value.AddMonths(1), minDate, maxDate); hover_lefts.Enable = Helper.DateExceed(value.AddYears(-1), minDate, maxDate); hover_rights.Enable = Helper.DateExceed(value.AddYears(1), minDate, maxDate); } } string year_str = ""; List GetCalendar(DateTime now) { var calendaris = new List(28); int days = DateTime.DaysInMonth(now.Year, now.Month); var now1 = new DateTime(now.Year, now.Month, 1); int day_ = 0; switch (now1.DayOfWeek) { case DayOfWeek.Tuesday: day_ = 1; break; case DayOfWeek.Wednesday: day_ = 2; break; case DayOfWeek.Thursday: day_ = 3; break; case DayOfWeek.Friday: day_ = 4; break; case DayOfWeek.Saturday: day_ = 5; break; case DayOfWeek.Sunday: day_ = 6; break; } if (day_ > 0) { var date1 = now.AddMonths(-1); int days2 = DateTime.DaysInMonth(date1.Year, date1.Month); for (int i = 0; i < day_; i++) { int day3 = days2 - i; calendaris.Insert(0, new Calendari(0, (day_ - 1) - i, 0, day3.ToString(), new DateTime(date1.Year, date1.Month, day3), minDate, maxDate)); } } int x = day_, y = 0; for (int i = 0; i < days; i++) { int day = i + 1; calendaris.Add(new Calendari(1, x, y, day.ToString(), new DateTime(now.Year, now.Month, day), minDate, maxDate)); x++; if (x > 6) { y++; x = 0; } } if (x < 7) { var date1 = now.AddMonths(1); int day2 = 0; for (int i = x; i < 7; i++) { int day3 = day2 + 1; calendaris.Add(new Calendari(2, x, y, day3.ToString(), new DateTime(date1.Year, date1.Month, day3), minDate, maxDate)); x++; day2++; } if (y < 5) { y++; for (int i = 0; i < 7; i++) { int day3 = day2 + 1; calendaris.Add(new Calendari(2, i, y, day3.ToString(), new DateTime(date1.Year, date1.Month, day3), minDate, maxDate)); day2++; } } } return calendaris; } /// /// 加载徽标 /// public void LoadBadge() { if (BadgeAction != null && calendar_day != null) { var oldval = _Date; ITask.Run(() => { var dir = BadgeAction(new DateTime[] { calendar_day[0].date, calendar_day[calendar_day.Count - 1].date }); if (_Date == oldval) { badge_list.Clear(); if (dir == null) { Invalidate(); return; } #if NET40 || NET46 || NET48 foreach (var it in dir) badge_list.Add(it.Date, it); #else foreach (var it in dir) badge_list.TryAdd(it.Date, it); #endif Invalidate(); } }); } } #endregion #region 参数 string button_text = Localization.Provider?.GetLocalizedString("ToDay") ?? "今天", OKButton = Localization.Provider?.GetLocalizedString("OK") ?? "确定", YearButton = Localization.Provider?.GetLocalizedString("Year") ?? "年", MonthButton = Localization.Provider?.GetLocalizedString("Month") ?? "月", MondayButton = Localization.Provider?.GetLocalizedString("Mon") ?? "一", TuesdayButton = Localization.Provider?.GetLocalizedString("Tue") ?? "二", WednesdayButton = Localization.Provider?.GetLocalizedString("Wed") ?? "三", ThursdayButton = Localization.Provider?.GetLocalizedString("Thu") ?? "四", FridayButton = Localization.Provider?.GetLocalizedString("Fri") ?? "五", SaturdayButton = Localization.Provider?.GetLocalizedString("Sat") ?? "六", SundayButton = Localization.Provider?.GetLocalizedString("Sun") ?? "日"; #endregion #endregion #region 渲染 StringFormat s_f = Helper.SF(); StringFormat s_f_L = Helper.SF(lr: StringAlignment.Far); StringFormat s_f_LE = Helper.SF_Ellipsis(lr: StringAlignment.Near); StringFormat s_f_R = Helper.SF(lr: StringAlignment.Near); protected override void OnPaint(PaintEventArgs e) { var g = e.Graphics.High(); var rect = ClientRectangle; var rect_read = ReadRectangle; using (var path = rect_read.RoundPath(radius * Config.Dpi)) { using (var brush = new SolidBrush(Style.Db.BgElevated)) { g.FillPath(brush, path); } } #region 方向 using (var pen_arrow = new Pen(Style.Db.TextTertiary, 1.6F * Config.Dpi)) using (var pen_arrow_hover = new Pen(Style.Db.Text, pen_arrow.Width)) using (var pen_arrow_enable = new Pen(Style.Db.FillSecondary, pen_arrow.Width)) { if (hover_lefts.Animation) { PointF[] tl1 = TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X - 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F), tl2 = TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X + 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F); g.DrawLines(pen_arrow, tl1); g.DrawLines(pen_arrow, tl2); using (var pen_arrow_hovers = new Pen(Helper.ToColor(hover_lefts.Value, pen_arrow_hover.Color), pen_arrow_hover.Width)) { g.DrawLines(pen_arrow_hovers, tl1); g.DrawLines(pen_arrow_hovers, tl2); } } else if (hover_lefts.Switch) { g.DrawLines(pen_arrow_hover, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X - 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); g.DrawLines(pen_arrow_hover, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X + 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); } else if (hover_lefts.Enable) { g.DrawLines(pen_arrow, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X - 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); g.DrawLines(pen_arrow, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X + 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); } else { g.DrawLines(pen_arrow_enable, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X - 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); g.DrawLines(pen_arrow_enable, TAlignMini.Left.TriangleLines(new Rectangle(rect_lefts.X + 4, rect_lefts.Y, rect_lefts.Width, rect_lefts.Height), .26F)); } if (hover_rights.Animation) { PointF[] tl1 = TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X - 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F), tl2 = TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X + 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F); g.DrawLines(pen_arrow, tl1); g.DrawLines(pen_arrow, tl2); using (var pen_arrow_hovers = new Pen(Helper.ToColor(hover_rights.Value, pen_arrow_hover.Color), pen_arrow_hover.Width)) { g.DrawLines(pen_arrow_hovers, tl1); g.DrawLines(pen_arrow_hovers, tl2); } } else if (hover_rights.Switch) { g.DrawLines(pen_arrow_hover, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X - 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); g.DrawLines(pen_arrow_hover, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X + 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); } else if (hover_rights.Enable) { g.DrawLines(pen_arrow, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X - 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); g.DrawLines(pen_arrow, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X + 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); } else { g.DrawLines(pen_arrow_enable, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X - 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); g.DrawLines(pen_arrow_enable, TAlignMini.Right.TriangleLines(new Rectangle(rect_rights.X + 4, rect_rights.Y, rect_rights.Width, rect_rights.Height), .26F)); } if (showType == 0) { if (hover_left.Animation) { var tl = TAlignMini.Left.TriangleLines(rect_left, .26F); g.DrawLines(pen_arrow, tl); using (var pen_arrow_hovers = new Pen(Helper.ToColor(hover_left.Value, pen_arrow_hover.Color), pen_arrow_hover.Width)) { g.DrawLines(pen_arrow_hovers, tl); } } else if (hover_left.Switch) g.DrawLines(pen_arrow_hover, TAlignMini.Left.TriangleLines(rect_left, .26F)); else if (hover_left.Enable) g.DrawLines(pen_arrow, TAlignMini.Left.TriangleLines(rect_left, .26F)); else g.DrawLines(pen_arrow_enable, TAlignMini.Left.TriangleLines(rect_left, .26F)); if (hover_right.Animation) { var tl = TAlignMini.Right.TriangleLines(rect_right, .26F); g.DrawLines(pen_arrow, tl); using (var pen_arrow_hovers = new Pen(Helper.ToColor(hover_right.Value, pen_arrow_hover.Color), pen_arrow_hover.Width)) { g.DrawLines(pen_arrow_hovers, tl); } } else if (hover_right.Switch) g.DrawLines(pen_arrow_hover, TAlignMini.Right.TriangleLines(rect_right, .26F)); else if (hover_right.Enable) g.DrawLines(pen_arrow, TAlignMini.Right.TriangleLines(rect_right, .26F)); else g.DrawLines(pen_arrow_enable, TAlignMini.Right.TriangleLines(rect_right, .26F)); } } #endregion if (showType == 1 && calendar_month != null) PrintMonth(g, rect_read, radius, calendar_month); else if (showType == 2 && calendar_year != null) PrintYear(g, rect_read, radius, calendar_year); else if (calendar_day != null) PrintDay(g, rect_read, radius, calendar_day); base.OnPaint(e); } #region 渲染帮助 #region 年模式 Rectangle rect_year_l; /// /// 渲染年模式 /// /// GDI /// 真实区域 /// 数据 void PrintYear(Graphics g, Rectangle rect_read, float radius, List datas) { using (var brush_fore_disable = new SolidBrush(Style.Db.TextQuaternary)) using (var brush_bg_disable = new SolidBrush(Style.Db.FillTertiary)) using (var brush_fore = new SolidBrush(Style.Db.TextBase)) { using (var font = new Font(Font.FontFamily, Font.Size, FontStyle.Bold)) { if (hover_year.Animation) { g.DrawStr(year_str, font, brush_fore, rect_year_l, s_f); using (var brush_hove = new SolidBrush(Helper.ToColor(hover_year.Value, Style.Db.Primary))) { g.DrawStr(year_str, font, brush_hove, rect_year_l, s_f); } } else if (hover_year.Switch) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.DrawStr(year_str, font, brush_hove, rect_year_l, s_f); } } else g.DrawStr(year_str, font, brush_fore, rect_year_l, s_f); } foreach (var it in datas) { using (var path = it.rect_read.RoundPath(radius)) { if (_value.ToString("yyyy") == it.date_str) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.FillPath(brush_hove, path); } using (var brush_active_fore = new SolidBrush(Style.Db.PrimaryColor)) { g.DrawStr(it.v, Font, brush_active_fore, it.rect, s_f); } } else if (it.enable) { if (it.hover) { using (var brush_hove = new SolidBrush(Style.Db.FillTertiary)) { g.FillPath(brush_hove, path); } } if (DateNow.ToString("yyyy-MM-dd") == it.date_str) { using (var brush_hove = new Pen(Style.Db.Primary, Config.Dpi)) { g.DrawPath(brush_hove, path); } } g.DrawStr(it.v, Font, it.t == 1 ? brush_fore : brush_fore_disable, it.rect, s_f); } else { g.FillRectangle(brush_bg_disable, new Rectangle(it.rect.X, it.rect_read.Y, it.rect.Width, it.rect_read.Height)); if (DateNow.ToString("yyyy-MM-dd") == it.date_str) { using (var brush_hove = new Pen(Style.Db.Primary, Config.Dpi)) { g.DrawPath(brush_hove, path); } } g.DrawStr(it.v, Font, brush_fore_disable, it.rect, s_f); } } } } } #endregion #region 月模式 Rectangle rect_month_l; /// /// 渲染月模式 /// /// GDI /// 真实区域 /// 数据 void PrintMonth(Graphics g, Rectangle rect_read, float radius, List datas) { using (var brush_fore_disable = new SolidBrush(Style.Db.TextQuaternary)) using (var brush_bg_disable = new SolidBrush(Style.Db.FillTertiary)) using (var brush_fore = new SolidBrush(Style.Db.TextBase)) { using (var font = new Font(Font.FontFamily, Font.Size, FontStyle.Bold)) { if (hover_year.Animation) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_fore, rect_month_l, s_f); using (var brush_hove = new SolidBrush(Helper.ToColor(hover_year.Value, Style.Db.Primary))) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_hove, rect_month_l, s_f); } } else if (hover_year.Switch) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_hove, rect_month_l, s_f); } } else g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_fore, rect_month_l, s_f); } foreach (var it in datas) { using (var path = it.rect_read.RoundPath(radius)) { if (_value.ToString("yyyy-MM") == it.date_str) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.FillPath(brush_hove, path); } using (var brush_active_fore = new SolidBrush(Style.Db.PrimaryColor)) { g.DrawStr(it.v, Font, brush_active_fore, it.rect, s_f); } } else if (it.enable) { if (it.hover) { using (var brush_hove = new SolidBrush(Style.Db.FillTertiary)) { g.FillPath(brush_hove, path); } } if (DateNow.ToString("yyyy-MM-dd") == it.date_str) { using (var brush_hove = new Pen(Style.Db.Primary, Config.Dpi)) { g.DrawPath(brush_hove, path); } } g.DrawStr(it.v, Font, brush_fore, it.rect, s_f); } else { g.FillRectangle(brush_bg_disable, new Rectangle(it.rect.X, it.rect_read.Y, it.rect.Width, it.rect_read.Height)); if (DateNow.ToString("yyyy-MM-dd") == it.date_str) { using (var brush_hove = new Pen(Style.Db.Primary, Config.Dpi)) { g.DrawPath(brush_hove, path); } } g.DrawStr(it.v, Font, brush_fore_disable, it.rect, s_f); } } } } } #endregion #region 天模式 Rectangle rect_day_l, rect_day_r; RectangleF rect_day_split1, rect_day_split2; Rectangle[]? rect_day_s; /// /// 渲染天模式 /// /// GDI /// 真实区域 /// 数据 void PrintDay(Graphics g, Rectangle rect_read, float radius, List datas) { if (rect_day_s == null) return; using (var brush_fore = new SolidBrush(Style.Db.TextBase)) { using (var font = new Font(Font.FontFamily, Font.Size, FontStyle.Bold)) { if (hover_year.Animation) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_fore, rect_day_l, s_f_L); using (var brush_hove = new SolidBrush(Helper.ToColor(hover_year.Value, Style.Db.Primary))) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_hove, rect_day_l, s_f_L); } } else if (hover_year.Switch) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_hove, rect_day_l, s_f_L); } } else g.DrawStr(_Date.ToString("yyyy") + YearButton, font, brush_fore, rect_day_l, s_f_L); if (hover_month.Animation) { g.DrawStr(_Date.ToString("MM") + MonthButton, font, brush_fore, rect_day_r, s_f_R); using (var brush_hove = new SolidBrush(Helper.ToColor(hover_month.Value, Style.Db.Primary))) { g.DrawStr(_Date.ToString("MM") + MonthButton, font, brush_hove, rect_day_r, s_f_R); } } else if (hover_month.Switch) { using (var brush_hove = new SolidBrush(Style.Db.Primary)) { g.DrawStr(_Date.ToString("MM") + MonthButton, font, brush_hove, rect_day_r, s_f_R); } } else g.DrawStr(_Date.ToString("MM") + MonthButton, font, brush_fore, rect_day_r, s_f_R); } using (var brush_split = new SolidBrush(Style.Db.Split)) { g.FillRectangle(brush_split, rect_day_split1); if (showButtonToDay) g.FillRectangle(brush_split, rect_day_split2); } using (var brush = new SolidBrush(Style.Db.Text)) { g.DrawStr(MondayButton, Font, brush, rect_day_s[0], s_f); g.DrawStr(TuesdayButton, Font, brush, rect_day_s[1], s_f); g.DrawStr(WednesdayButton, Font, brush, rect_day_s[2], s_f); g.DrawStr(ThursdayButton, Font, brush, rect_day_s[3], s_f); g.DrawStr(FridayButton, Font, brush, rect_day_s[4], s_f); g.DrawStr(SaturdayButton, Font, brush, rect_day_s[5], s_f); g.DrawStr(SundayButton, Font, brush, rect_day_s[6], s_f); } using (var brush_fore_disable = new SolidBrush(Style.Db.TextQuaternary)) using (var brush_bg_disable = new SolidBrush(Style.Db.FillTertiary)) using (var brush_active = new SolidBrush(Style.Db.Primary)) using (var brush_active_fore = new SolidBrush(Style.Db.PrimaryColor)) using (var brush_error = new SolidBrush(Style.Db.Error)) { PaintToDayFrame(g, datas, DateNow.ToString("yyyy-MM-dd"), radius); if (chinese) { using (var font4 = new Font(Font.FontFamily, Font.Size * .76F, Font.Style)) { using (var brush_fore_c = new SolidBrush(Style.Db.TextSecondary)) { foreach (var it in datas) { using (var path = it.rect_read.RoundPath(radius)) { var cdate = ChineseCalendar.ChineseDate.From(it.date); if (_value.ToString("yyyy-MM-dd") == it.date_str) { g.FillPath(brush_active, path); g.DrawStr(cdate.DayString, font4, brush_active_fore, it.rect_l, s_f); g.DrawStr(it.v, Font, brush_active_fore, it.rect_f, s_f); } else if (it.enable) { if (it.hover) { using (var brush_hove = new SolidBrush(Style.Db.FillTertiary)) { g.FillPath(brush_hove, path); } } g.DrawStr(cdate.DayString, font4, brush_fore_c, it.rect_l, s_f); g.DrawStr(it.v, Font, it.t == 1 ? brush_fore : brush_fore_disable, it.rect_f, s_f); } else { g.FillRectangle(brush_bg_disable, new Rectangle(it.rect.X, it.rect_read.Y, it.rect.Width, it.rect_read.Height)); g.DrawStr(cdate.DayString, font4, brush_fore_disable, it.rect_l, s_f); g.DrawStr(it.v, Font, brush_fore_disable, it.rect_f, s_f); } } } } } } else { foreach (var it in datas) { using (var path = it.rect_read.RoundPath(radius)) { if (_value.ToString("yyyy-MM-dd") == it.date_str) { g.FillPath(brush_active, path); g.DrawStr(it.v, Font, brush_active_fore, it.rect, s_f); } else if (it.enable) { if (it.hover) { using (var brush_hove = new SolidBrush(Style.Db.FillTertiary)) { g.FillPath(brush_hove, path); } } g.DrawStr(it.v, Font, it.t == 1 ? brush_fore : brush_fore_disable, it.rect, s_f); } else { g.FillRectangle(brush_bg_disable, new Rectangle(it.rect.X, it.rect_read.Y, it.rect.Width, it.rect_read.Height)); g.DrawStr(it.v, Font, brush_fore_disable, it.rect, s_f); } } } } if (showButtonToDay) { if (hover_button.Animation) { g.DrawStr(button_text, Font, brush_active, rect_button, s_f); using (var brush_hove = new SolidBrush(Helper.ToColor(hover_button.Value, Style.Db.PrimaryActive))) { g.DrawStr(button_text, Font, brush_hove, rect_button, s_f); } } else if (hover_button.Switch) { using (var brush_hove = new SolidBrush(Style.Db.PrimaryActive)) { g.DrawStr(button_text, Font, brush_hove, rect_button, s_f); } } else g.DrawStr(button_text, Font, brush_active, rect_button, s_f); } if (badge_list.Count > 0) { using (var font = new Font(Font.FontFamily, Font.Size * BadgeSize)) { foreach (var it in datas) { if (badge_list.TryGetValue(it.date_str, out var find)) this.PaintBadge(find, font, it.rect, g); } } } } } } /// /// 绘制今天边框 /// internal static void PaintToDayFrame(Graphics g, IList datas, string dateNow, float radius) { foreach (var it in datas) { if (dateNow == it.date_str) { using (var path = it.rect_read.RoundPath(radius)) { using (var pen_active = new Pen(Style.Db.Primary, Config.Dpi)) { g.DrawPath(pen_active, path); } } return; } } } #endregion public override Rectangle ReadRectangle { get => ClientRectangle.PaddingRect(Padding); } public override GraphicsPath RenderRegion { get { var rect_read = ReadRectangle; float _radius = radius * Config.Dpi; return rect_read.RoundPath(_radius); } } #endregion #endregion #region 鼠标 ITaskOpacity hover_button, hover_lefts, hover_left, hover_rights, hover_right, hover_year, hover_month; Rectangle rect_button = new Rectangle(-20, -20, 10, 10); Rectangle rect_lefts = new Rectangle(-20, -20, 10, 10), rect_left = new Rectangle(-20, -20, 10, 10); Rectangle rect_rights = new Rectangle(-20, -20, 10, 10), rect_right = new Rectangle(-20, -20, 10, 10); Rectangle rect_year = new Rectangle(-20, -20, 10, 10), rect_year2 = new Rectangle(-20, -20, 10, 10), rect_month = new Rectangle(-20, -20, 10, 10); protected override void OnMouseMove(MouseEventArgs e) { int count = 0, hand = 0; bool _hover_lefts = rect_lefts.Contains(e.X, e.Y), _hover_rights = rect_rights.Contains(e.X, e.Y), _hover_left = (showType == 0 && rect_left.Contains(e.X, e.Y)), _hover_right = (showType == 0 && rect_right.Contains(e.X, e.Y)), _hover_button = (showType == 0 && showButtonToDay && rect_button.Contains(e.X, e.Y)); bool _hover_year = false, _hover_month = false; if (showType != 2) { _hover_year = showType == 0 ? rect_year.Contains(e.X, e.Y) : rect_year2.Contains(e.X, e.Y); _hover_month = rect_month.Contains(e.X, e.Y); } if (_hover_lefts != hover_lefts.Switch) count++; if (_hover_left != hover_left.Switch) count++; if (_hover_rights != hover_rights.Switch) count++; if (_hover_right != hover_right.Switch) count++; if (_hover_year != hover_year.Switch) count++; if (_hover_month != hover_month.Switch) count++; if (_hover_button != hover_button.Switch) count++; hover_lefts.Switch = _hover_lefts; hover_left.Switch = _hover_left; hover_rights.Switch = _hover_rights; hover_right.Switch = _hover_right; hover_year.Switch = _hover_year; hover_month.Switch = _hover_month; hover_button.Switch = _hover_button; if (hover_lefts.Switch || hover_left.Switch || hover_rights.Switch || hover_right.Switch || hover_year.Switch || hover_month.Switch || hover_button.Switch) hand++; else { if (showType == 1) { if (calendar_month != null) { foreach (var it in calendar_month) { bool hove = it.enable && it.rect.Contains(e.X, e.Y); if (it.hover != hove) count++; it.hover = hove; if (it.hover) hand++; } } } else if (showType == 2) { if (calendar_year != null) { foreach (var it in calendar_year) { bool hove = it.enable && it.rect.Contains(e.X, e.Y); if (it.hover != hove) count++; it.hover = hove; if (it.hover) hand++; } } } else { if (calendar_day != null) { foreach (var it in calendar_day) { bool hove = it.enable && it.rect.Contains(e.X, e.Y); if (it.hover != hove) count++; it.hover = hove; if (it.hover) hand++; } } } } if (count > 0) Invalidate(); SetCursor(hand > 0); base.OnMouseMove(e); } protected override void OnMouseLeave(EventArgs e) { hover_lefts.Switch = false; hover_left.Switch = false; hover_rights.Switch = false; hover_right.Switch = false; hover_year.Switch = false; hover_month.Switch = false; hover_button.Switch = false; if (calendar_year != null) { foreach (var it in calendar_year) it.hover = false; } if (calendar_month != null) { foreach (var it in calendar_month) it.hover = false; } if (calendar_day != null) { foreach (var it in calendar_day) it.hover = false; } SetCursor(false); Invalidate(); base.OnMouseLeave(e); } int showType = 0; void ChangeType(int type) { if (type == showType) return; showType = type; OnSizeChanged(EventArgs.Empty); Invalidate(); } protected override void OnMouseUp(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (rect_lefts.Contains(e.X, e.Y)) { if (hover_lefts.Enable) { if (showType == 2) Date = _Date.AddYears(-10); else Date = _Date.AddYears(-1); Invalidate(); } return; } else if (rect_rights.Contains(e.X, e.Y)) { if (hover_rights.Enable) { if (showType == 2) Date = _Date.AddYears(10); else Date = _Date.AddYears(1); Invalidate(); } return; } else if (showType == 0 && rect_left.Contains(e.X, e.Y)) { if (hover_left.Enable) { Date = _Date.AddMonths(-1); Invalidate(); } return; } else if (showType == 0 && rect_right.Contains(e.X, e.Y)) { if (hover_right.Enable) { Date = _Date.AddMonths(1); Invalidate(); } return; } else if ((showType == 0 && rect_year.Contains(e.X, e.Y)) || (showType != 0 && rect_year2.Contains(e.X, e.Y))) { ChangeType(2); return; } else if (showType == 0 && showButtonToDay && rect_button.Contains(e.X, e.Y)) { Value = Date = DateNow = DateTime.Now; return; } else if (rect_month.Contains(e.X, e.Y)) { ChangeType(1); return; } else { if (showType == 1) { if (calendar_month != null) { foreach (var it in calendar_month) { if (it.enable && it.rect.Contains(e.X, e.Y)) { Date = it.date; ChangeType(0); return; } } } } else if (showType == 2) { if (calendar_year != null) { foreach (var it in calendar_year) { if (it.enable && it.rect.Contains(e.X, e.Y)) { Date = it.date; ChangeType(1); return; } } } } else { if (calendar_day != null) { foreach (var it in calendar_day) { if (it.enable && it.rect.Contains(e.X, e.Y)) { Value = it.date; return; } } } } } } base.OnMouseUp(e); } protected override void OnMouseWheel(MouseEventArgs e) { if (e.Delta != 0) MouseWheelDay(e); base.OnMouseWheel(e); } void MouseWheelDay(MouseEventArgs e) { if (e.Delta > 0) { if (showType == 1) { if (hover_lefts.Enable) Date = _Date.AddYears(-1); else return; } else if (showType == 2) { if (hover_lefts.Enable) Date = _Date.AddYears(-10); else return; } else { if (hover_left.Enable) Date = _Date.AddMonths(-1); else return; } Invalidate(); } else { if (showType == 1) { if (hover_rights.Enable) Date = _Date.AddYears(1); else return; } else if (showType == 2) { if (hover_rights.Enable) Date = _Date.AddYears(10); else return; } else { if (hover_right.Enable) Date = _Date.AddMonths(1); else return; } Invalidate(); } } #endregion #region 坐标 protected override void OnSizeChanged(EventArgs e) { float dpi = Config.Dpi; var rect = ReadRectangle; int t_top = 34, t_button = showButtonToDay ? 38 : 0; int year_width = 60, year2_width = 88, month_width = 40; if (dpi != 1F) { t_top = (int)(t_top * dpi); if (showButtonToDay) t_button = (int)(t_button * dpi); year_width = (int)(year_width * dpi); year2_width = (int)(year2_width * dpi); month_width = (int)(month_width * dpi); } rect_lefts = new Rectangle(rect.X, rect.Y, t_top, t_top); rect_left = new Rectangle(rect.X + t_top, rect.Y, t_top, t_top); rect_rights = new Rectangle(rect.X + rect.Width - t_top, rect.Y, t_top, t_top); rect_right = new Rectangle(rect.X + rect.Width - t_top * 2, rect.Y, t_top, t_top); rect_year = new Rectangle(rect.X + rect.Width / 2 - year_width, rect.Y, year_width, t_top); rect_year2 = new Rectangle(rect.X + (rect.Width - year2_width) / 2, rect.Y, year2_width, t_top); rect_month = new Rectangle(rect.X + rect.Width / 2, rect.Y, month_width, t_top); rect_button = new Rectangle(rect.X, rect.Bottom - t_button, rect.Width, t_button); #region 计算坐标 int gap_day = (int)(8 * dpi), gap_day2 = gap_day * 2; if (showType == 1) { //月 rect_month_l = new Rectangle(rect.X, rect.Y, rect.Width, t_top); int y = rect.Y + t_top; int size_w = (rect.Width - gap_day2) / 3, size_h = (rect.Height - t_top - gap_day2) / 4; if (calendar_month != null) { foreach (var it in calendar_month) it.rect = new Rectangle(rect.X + gap_day + (size_w * it.x), y + gap_day + (size_h * it.y), size_w, size_h); } } else if (showType == 2) { //年 rect_year_l = new Rectangle(rect.X, rect.Y, rect.Width, t_top); int y = rect.Y + t_top; int size_w = (rect.Width - gap_day2) / 3, size_h = (rect.Height - t_top - gap_day2) / 4; if (calendar_year != null) { foreach (var it in calendar_year) it.rect = new Rectangle(rect.X + gap_day + (size_w * it.x), y + gap_day + (size_h * it.y), size_w, size_h); } } else { if (chinese) { int y = rect.Y + t_top + 12, xm = rect.Width / 2; int size_w = (rect.Width - gap_day2) / 7, size_h = (rect.Height - t_top - t_button - gap_day2) / 7; rect_day_l = new Rectangle(rect.X, rect.Y, xm, t_top); rect_day_r = new Rectangle(rect.X + xm, rect.Y, xm, t_top); rect_day_split1 = new RectangleF(rect.X, rect.Y + t_top, rect.Width, 1F); if (showButtonToDay) rect_day_split2 = new RectangleF(rect.X, rect_button.Y - .5F, rect.Width, 1); rect_day_s = new Rectangle[]{ new Rectangle(rect.X + gap_day, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 2, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 3, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 4, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 5, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 6, y, size_w, size_h) }; y += size_h; if (calendar_day != null) { foreach (var it in calendar_day) { it.SetRectG(new Rectangle(rect.X + gap_day + (size_w * it.x), y + (size_h * it.y), size_w, size_h), .92F); it.rect_f = new Rectangle(it.rect_read.X, it.rect_read.Y, it.rect_read.Width, it.rect_read.Height - it.rect_read.Height / 4); it.rect_l = new Rectangle(it.rect_read.X, it.rect_read.Y + it.rect_read.Height / 2, it.rect_read.Width, it.rect_read.Height / 2); } } } else if (full) { int y = rect.Y + t_top + 12, xm = rect.Width / 2; int size_w = (rect.Width - gap_day2) / 7, size_h = (rect.Height - t_top - t_button - gap_day2) / 7; rect_day_l = new Rectangle(rect.X, rect.Y, xm, t_top); rect_day_r = new Rectangle(rect.X + xm, rect.Y, xm, t_top); rect_day_split1 = new RectangleF(rect.X, rect.Y + t_top, rect.Width, 1F); if (showButtonToDay) rect_day_split2 = new RectangleF(rect.X, rect_button.Y - .5F, rect.Width, 1); rect_day_s = new Rectangle[]{ new Rectangle(rect.X + gap_day, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 2, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 3, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 4, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 5, y, size_w, size_h), new Rectangle(rect.X + gap_day + size_w * 6, y, size_w, size_h) }; y += size_h; if (calendar_day != null) { foreach (var it in calendar_day) it.SetRectG(new Rectangle(rect.X + gap_day + (size_w * it.x), y + (size_h * it.y), size_w, size_h), .92F); } } else { int y = rect.Y + t_top + 12, xm = rect.Width / 2; int size_w = (rect.Width - gap_day2) / 7, size_h = (rect.Height - t_top - t_button - gap_day2) / 7, size = size_w; if (size_w > size_h) { size = size_h; gap_day2 = rect.Width - size * 7; gap_day = gap_day2 / 2; } rect_day_l = new Rectangle(rect.X, rect.Y, xm, t_top); rect_day_r = new Rectangle(rect.X + xm, rect.Y, xm, t_top); rect_day_split1 = new RectangleF(rect.X, rect.Y + t_top, rect.Width, 1F); if (showButtonToDay) rect_day_split2 = new RectangleF(rect.X, rect_button.Y - .5F, rect.Width, 1); rect_day_s = new Rectangle[]{ new Rectangle(rect.X + gap_day, y, size, size), new Rectangle(rect.X + gap_day + size, y, size, size), new Rectangle(rect.X + gap_day + size * 2, y, size, size), new Rectangle(rect.X + gap_day + size * 3, y, size, size), new Rectangle(rect.X + gap_day + size * 4, y, size, size), new Rectangle(rect.X + gap_day + size * 5, y, size, size), new Rectangle(rect.X + gap_day + size * 6, y, size, size) }; y += size; if (calendar_day != null) { int size_one = (int)(size * .666F); foreach (var it in calendar_day) it.SetRect(new Rectangle(rect.X + gap_day + (size * it.x), y + (size * it.y), size, size), size_one); } } } #endregion base.OnSizeChanged(e); } #endregion #region 事件 [Description("日期 改变时发生"), Category("行为")] public event DateTimeEventHandler? DateChanged; #endregion protected override void Dispose(bool disposing) { hover_lefts?.Dispose(); hover_left?.Dispose(); hover_rights?.Dispose(); hover_right?.Dispose(); hover_year?.Dispose(); hover_month?.Dispose(); hover_button?.Dispose(); base.Dispose(disposing); } } }