using ryCommon; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static ryControls.FhChinaCalendar; using static ScintillaNETV2.Style; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Header; namespace ryControls { /// /// 日历控件,不含月份和年份选择 /// [DefaultEvent("OnDateTimeChanged")] [Description("农历日历控件")] [ToolboxBitmap(typeof(System.Windows.Forms.MonthCalendar))] public partial class PaChinaCalendar : UserControl { /// /// /// public PaChinaCalendar() : base() { InitializeComponent(); this.DoubleBuffered = true; } /// /// 选择的日期变化时激发 /// [Description("选择的日期变化时激发")] public event EventHandler OnDateTimeChanged; private int _itemSize = 80; /// /// 单项大小 /// [Description("单项大小")] public int ItemSize { get { return _itemSize; } set { if (_itemSize == value) { return; } _itemSize =value; this.Invalidate(); } } private string holiday_folder = ".\\SysDb\\Holidays"; /// /// 放假数据表 /// public string HolidayFolder { get { return holiday_folder; } set { if (holiday_folder == value) { return; } holiday_folder = value; this.Invalidate(); } } private DateTime _DateTime = DateTime.Now; /// /// 当前选择的时间 /// [Description("当前选择的时间")] public DateTime DateTime { get { return _DateTime; } set { if (_DateTime.Date == value.Date) { return; } _DateTime = value; this.Invalidate(); OnDateTimeChanged?.Invoke(this, new EventArgs()); } } private Font _DayFont = new Font("微软雅黑", 14,FontStyle.Bold); /// /// 阳历天字体 /// [Description("阳历天字体")] public Font DayFont { get { return _DayFont; } set { if (_DayFont == value) { return; } _DayFont = value; this.Invalidate(); } } private Font _ChinaDayFont = new Font("微软雅黑", 10); /// /// 农历天字体 /// [Description("农历天字体")] public Font ChinaDayFont { get { return _ChinaDayFont; } set { if (_ChinaDayFont == value) { return; } _ChinaDayFont = value; this.Invalidate(); } } private int _HeaderHeight = 30; /// /// 标头高度(星期高度) /// [Description("标头高度(星期高度)")] public int HeaderHeight { get { return _HeaderHeight; } set { if (_HeaderHeight == value) { return; } _HeaderHeight = value; this.Invalidate(); } } private int _CellSpace = 1; /// /// 列间距 /// [Description("列间距")] public int CellSpace { get { return _CellSpace; } set { if (_CellSpace == value) { return; } _CellSpace = value; this.Invalidate(); } } private int _RowSpace = 1; /// /// 行间距 /// [Description("行间距")] public int RowSpace { get { return _RowSpace; } set { if (_RowSpace == value) { return; } _RowSpace = value; this.Invalidate(); } } private Font _HeaderFont = new Font("微软雅黑",11); /// /// 星期字体 /// [Description("星期字体")] public Font HeaderFont { get { return _HeaderFont; } set { if (_HeaderFont == value) { return; } _HeaderFont = value; this.Invalidate(); } } private Color _HolidayForeColor = Color.Orange; /// /// 节日颜色 /// [Description("节日颜色")] public Color HolidayForeColor { get { return _HolidayForeColor; } set { if (_HolidayForeColor == value) { return; } _HolidayForeColor = value; this.Invalidate(); } } private int _Mode = 0; /// /// 模式(0表示日模式,1表示月份展示模式,2表示年份展示模式) /// [Description("模式(0表示日模式,1表示月份展示模式,2表示年份展示模式)")] public int Mode { get { return _Mode; } set { if (_Mode == value) { return; } if(value < 0 && value > 2) { return; } _Mode = value; ClearPaint = true; this.Invalidate(); } } private bool ClearPaint { get; set; } = false; private int _PaddingLeft = 0; /// /// 左边距 /// [Description("左边距")] public int PaddingLeft { get { return _PaddingLeft; } set { if (_PaddingLeft == value) { return; } _PaddingLeft = value; this.Invalidate(); } } private int _PaddingTop = 0; /// /// 顶部边距 /// [Description("顶部边距")] public int PaddingTop { get { return _PaddingTop; } set { if (_PaddingTop == value) { return; } _PaddingTop = value; this.Invalidate(); } } /// /// /// /// protected override void OnSizeChanged(EventArgs e) { this.Invalidate(); base.OnSizeChanged(e); } /// /// 单击某个日期事件 /// public event ClickItemHandler OnClickItem; /// /// /// /// protected override void OnMouseDown(MouseEventArgs e) { //获取点击的是第几行(1-6行) using (lock_dayitem.Read()) { for (int i = 0; i < list_rect.Count; i++) { if (list_rect[i].Rect.Contains(e.Location)) { DateTime = list_rect[i].Date; OnClickItem?.Invoke(this, list_rect[i].Date); break; } } } base.OnMouseDown(e); } /// /// /// /// protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Right: DateTime = DateTime.AddDays(1); break; case Keys.Left: DateTime = DateTime.AddDays(-1); break; case Keys.Up://方向键不反应 DateTime = DateTime.AddDays(-7); break; case Keys.Down: DateTime = DateTime.AddDays(7); break; case Keys.Enter: OnClickItem?.Invoke(this, DateTime); break; } base.OnKeyDown(e); } /// /// /// /// /// protected override bool IsInputKey(Keys keyData) { // 确保UserControl接收所有键盘输入 if (keyData == Keys.Up || keyData == Keys.Down || keyData == Keys.Left || keyData == Keys.Right) { return true; } return base.IsInputKey(keyData); } /// /// 是否处于设计模式 /// /// public bool IsDesignMode() { bool returnFlag = this.DesignMode; #if DEBUG if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) { returnFlag = true; } else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv") { returnFlag = true; } #endif return returnFlag; } private DateTime dt_start { get; set; } = DateTime.Now; private readonly List list_rect = []; private readonly rySafe.UsingLock lock_dayitem=new rySafe.UsingLock(); /// /// /// /// protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (ClearPaint) { ClearPaint = false; e.Graphics.Clear(this.BackColor); } StringFormat stringFormat = new StringFormat(); stringFormat.LineAlignment = StringAlignment.Center; stringFormat.Alignment = StringAlignment.Center; stringFormat.Trimming = StringTrimming.EllipsisCharacter; stringFormat.FormatFlags = StringFormatFlags.NoWrap; if (Mode == 0) //日模式 { #region 日模式 #region 列头 for (int i = 0; i < 7; i++) { e.Graphics.DrawString("周" + RyDate.GetWeekName(i + 1), _HeaderFont, Brushes.Black, new RectangleF(PaddingLeft + i * (_itemSize + CellSpace), PaddingTop, _itemSize, _HeaderHeight), stringFormat); } e.Graphics.DrawLine(Pens.LightGray, PaddingLeft, HeaderHeight, PaddingLeft + 6 * (_itemSize + CellSpace) + _itemSize, PaddingTop + HeaderHeight); #endregion var gl_daycount = 0; if (_DateTime.Year < 1582 || (_DateTime.Year == 1582 && _DateTime.Month <= 10)) { gl_daycount = 11; } var month_date = RyDate.GetMonthStart(_DateTime); var start_week = RyDate.GetWeek_index(month_date.AddDays(-gl_daycount)); DateTime? dt_1fu = null; DateTime? dt_2fu = null; DateTime? dt_3fu = null; if (_DateTime.Month == 7 || _DateTime.Month == 8) { dt_1fu = ChinaDate.Get3Fu(_DateTime.Year, 0); dt_2fu = dt_1fu.Value.AddDays(10); dt_3fu = ChinaDate.Get3Fu(_DateTime.Year, 2); } var row_y = PaddingTop + HeaderHeight + 2; dt_start = month_date.AddDays(1 - start_week); using (lock_dayitem.Write()) { list_rect.Clear(); Ini ini = null; if (!IsDesignMode()) { var ini_path = holiday_folder + "\\" + DateTime.Year + ".ini"; if (holiday_folder.StartsWith(".\\")) { ini_path = Application.StartupPath + "\\" + holiday_folder.Substring(2) + "\\" + DateTime.Year + ".ini"; } if (System.IO.File.Exists(ini_path)) { ini = new Ini(ini_path); } } for (int i = 0; i < 42; i++) { if (i > 0 && i % 7 == 0) { row_y += _itemSize + RowSpace; } #region 获取农历阳历信息 var dt_2 = month_date.AddDays(i + 1 - start_week); if (month_date.Year == 1582 && month_date.Month == 10) { if (i >= 4) { dt_2 = dt_2.AddDays(10); } } if (i >= 35) { if (month_date.AddDays(36 - start_week).Month != _DateTime.Month) { break; } } var rest_state = 0; if (dt_2.Year == _DateTime.Year) { if (ini != null) { int state = ini.ReadIni("date", dt_2.ToString("MMdd"), -2); if (state != -2) { rest_state = state; } } } else { if (ini != null) { var ini_path2 = holiday_folder + "\\" + dt_2.Year + ".ini"; if (holiday_folder.StartsWith(".\\")) { ini_path2 = Application.StartupPath + "\\" + holiday_folder.Substring(2) + "\\" + dt_2.Year + ".ini"; } if (System.IO.File.Exists(ini_path2)) { Ini ini2 = new Ini(ini_path2); int state = ini2.ReadIni("date", dt_2.ToString("MMdd"), -2); if (state != -2) { rest_state = state; } } } } var ChinaHoliday = ChinaDate.GetChinaHoliday(dt_2); var WorldHoliday = ChinaDate.GetHoliday(dt_2); var WeekHoliday = ChinaDate.GetWeekHoliday(dt_2); var JieqiHoliday = ChinaDate.GetSolarTerm(dt_2); bool Holiday = false; string Holiday_Str = ""; if (ChinaHoliday != "") { Holiday_Str = ChinaHoliday; } if (dt_2 == dt_1fu) { Holiday_Str += " 初伏"; } if (dt_2 == dt_2fu) { Holiday_Str += " 中伏"; } if (dt_2 == dt_3fu) { Holiday_Str += " 末伏"; } if (WorldHoliday != "") { Holiday_Str += " " + WorldHoliday; } if (WeekHoliday != "") { Holiday_Str += " " + WeekHoliday; } if (JieqiHoliday != "") { Holiday_Str += " " + JieqiHoliday; } var Lunar_Day = Holiday_Str.Trim(); if (Lunar_Day.Length == 0) { var lunar_day_str = ChinaDate.GetDay(dt_2); if (lunar_day_str == "初一") { Lunar_Day = ChinaDate.GetMonth(dt_2); } else { Lunar_Day = lunar_day_str; } } else { Holiday = true; } #endregion //写阳历天 var Rect = new Rectangle(PaddingLeft + (i % 7) * (_itemSize + CellSpace), row_y, _itemSize, _itemSize); list_rect.Add(new DayItem() { Rect = Rect, DayText = dt_2.Day.ToString(), ChinaDayText = Lunar_Day, Date = dt_2.Date, RestState = rest_state, IsHoliday = Holiday }); } } #endregion } else if (Mode == 1) //月模式 { var row_y = PaddingTop + HeaderHeight + 2; dt_start = this.DateTime.AddMonths(-this.DateTime.Month+1); using (lock_dayitem.Write()) { list_rect.Clear(); var aSize = (this.Width - PaddingLeft - PaddingLeft - CellSpace * 3) / 4; var months = new string[] { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" }; for (int i = 0; i < 12; i++) { if (i > 0 && i % 4 == 0) { row_y += aSize + RowSpace; } var Rect = new Rectangle(PaddingLeft + (i % 4) * (aSize + CellSpace), row_y, aSize, aSize); var dt_2 = dt_start.AddMonths(i); list_rect.Add(new DayItem() { Mode=1, Rect = Rect, DayText = months[i], Date = dt_2.Date, }); } } } else if (Mode == 2) //年模式 { var row_y = PaddingTop + HeaderHeight + 2; dt_start = this.DateTime.AddYears(-this.DateTime.Year%10-1); using (lock_dayitem.Write()) { list_rect.Clear(); var aSize = (this.Width - PaddingLeft - PaddingLeft - CellSpace * 3) / 4; for (int i = 0; i < 12; i++) { if (i > 0 && i % 4 == 0) { row_y += aSize + RowSpace; } var Rect = new Rectangle(PaddingLeft + (i % 4) * (aSize + CellSpace), row_y, aSize, aSize); var dt_2 = dt_start.AddYears(i); list_rect.Add(new DayItem() { Mode = 2, Rect = Rect, DayText = dt_2.Year.ToString() + "年", Date = dt_2.Date, }); } } } using (lock_dayitem.Read()) { var day_size = e.Graphics.MeasureString("1", _DayFont); var china_day_size = e.Graphics.MeasureString("中秋", _ChinaDayFont); int allday_height = (day_size.Height + china_day_size.Height).ToInt() + 2; var day_top = (_itemSize - allday_height) / 2; var china_day_top = day_top + day_size.Height.ToInt(); for (int i = 0; i < list_rect.Count; i++) { var item = list_rect[i]; if (item.Mode == 0) { if (item.Date == _DateTime.Date) { //渐变画刷 LinearGradientBrush brush = new LinearGradientBrush(item.Rect, Color.FromArgb(240, 230, 200), Color.FromArgb(255, 236, 181), LinearGradientMode.Vertical); //填充区域 //Rectangle borderRect = new Rectangle(r, e.Bounds.Y, e.Bounds.Width - 5, e.Bounds.Height - 2); e.Graphics.FillRectangle(brush, item.Rect); brush.Dispose(); ////画边框 Pen pen = new Pen(Color.FromArgb(229, 195, 101)); Rectangle borderRect = item.Rect; borderRect.Width--; borderRect.Height--; e.Graphics.DrawRectangle(pen, borderRect); pen.Dispose(); //e.Graphics.DrawRectangle(Pens.LightGray, Rect); } else if (item.Date == DateTime.Now.Date) { Pen pen = new Pen(Color.FromArgb(229, 195, 101)); Rectangle borderRect = item.Rect; borderRect.Width--; borderRect.Height--; e.Graphics.DrawRectangle(pen, borderRect); pen.Dispose(); } e.Graphics.DrawString(item.DayText, _DayFont, item.Date.Month != _DateTime.Month ? Brushes.Gray : Brushes.Black, new Rectangle() { X = item.Rect.X, Y = item.Rect.Y + day_top, Width = _itemSize, Height = day_size.Height.ToInt() }, stringFormat); e.Graphics.DrawString(item.ChinaDayText, _ChinaDayFont, item.Date.Month != _DateTime.Month ? Brushes.Gray : (item.IsHoliday ? new SolidBrush(_HolidayForeColor) : Brushes.Black), new Rectangle() { X = item.Rect.X, Y = item.Rect.Y + china_day_top, Width = _itemSize, Height = china_day_size.Height.ToInt() }, stringFormat); } else { if(item.Mode==1 && item.Date.Month == _DateTime.Month) { //渐变画刷 LinearGradientBrush brush = new LinearGradientBrush(item.Rect, Color.FromArgb(240, 230, 200), Color.FromArgb(255, 236, 181), LinearGradientMode.Vertical); //填充区域 //Rectangle borderRect = new Rectangle(r, e.Bounds.Y, e.Bounds.Width - 5, e.Bounds.Height - 2); e.Graphics.FillRectangle(brush, item.Rect); brush.Dispose(); ////画边框 Pen pen = new Pen(Color.FromArgb(229, 195, 101)); Rectangle borderRect = item.Rect; borderRect.Width--; borderRect.Height--; e.Graphics.DrawRectangle(pen, borderRect); pen.Dispose(); } else if (item.Mode == 2 && item.Date.Year == _DateTime.Year) { //渐变画刷 LinearGradientBrush brush = new LinearGradientBrush(item.Rect, Color.FromArgb(240, 230, 200), Color.FromArgb(255, 236, 181), LinearGradientMode.Vertical); //填充区域 //Rectangle borderRect = new Rectangle(r, e.Bounds.Y, e.Bounds.Width - 5, e.Bounds.Height - 2); e.Graphics.FillRectangle(brush, item.Rect); brush.Dispose(); ////画边框 Pen pen = new Pen(Color.FromArgb(229, 195, 101)); Rectangle borderRect = item.Rect; borderRect.Width--; borderRect.Height--; e.Graphics.DrawRectangle(pen, borderRect); pen.Dispose(); } e.Graphics.DrawString(item.DayText, _DayFont, (Mode==2 && (i==0 || i==list_rect.Count-1))? Brushes.Gray: Brushes.Black, item.Rect, stringFormat); } } } } private class DayItem { /// /// 0表示日模式,1表示月份展示模式,2表示年份展示模式 /// public int Mode { get; set; } = 0; public DateTime Date { get; set; } = DateTime.MinValue; /// /// 显示的位置 /// public Rectangle Rect { get; set; } public string DayText { get; set; } = ""; public string ChinaDayText { get; set; } = ""; /// /// 是否是节假日 /// public bool IsHoliday { get; set; } = false; /// /// 休息状态,1为休息,-1为上班 /// public int RestState { get; set; } = 0; } } }