RaUI/Source/RaUI/UI/Rili/PaChinaCalendar.cs
zilinsoft 7ff45b3074 ## 📅2026-06-04 星期四更新
### RaUI    V4.0.2606.0401
- *.[新增]QuickWeb新增支持重试次数。
- *.[新增]RySetting类新增支持json格式设置存储和获取。
- *.[新增]RySetting类新增支持读取设置到内存,然后按配置名称读取。
- *.[新增]新增SuperFileSearch类,文件查找。
- *.[新增]QuickWeb新增CurPageUrl属性。
- *.[新增]HardWare新增支持获取显示器信息。
- *.[新增]HardWare新增GetWMI函数。
- *.[改进]QuickWeb类的UA从IE改为Edge。
- *.[改进]Hosts类IP与域名分隔符从\t改为三个空格。
- *.[改进]RyImage的CropOrFill函数,如果输入的长宽比例与原图一致,则返回原图的副本而不是原图。
- *.[改进]RySoft类的CompareVer函数支持特殊格式的版本号。
- *.[改进]QuickWeb的ConvertUrl函数新增支持自动从CurPageUrl获取。
- *.[改进]DateDiff函数对时间差异小于等于10秒的,自动加上毫秒数据。
- *.[修复]修复ObjectListView控件的AspectGetter方法可能调用null对象的问题。
- *.[修复]修复日期选择控件在获取节假日数据时,会因为节假日文件夹无法访问而报错的问题。
- *.[修复]修复某些情况下剪切板权限问题导致ObjectListView控件报错。
- *.[修复]修复RyImage的CropOrFill函数图片比例不一致时,也是返回原图副本的BUG。
### Itrycn_Project2    V1.0.2606.0401
- *.[改进]将公共调用,无需新增内容的部分代码,改到Public文件夹下
2026-06-04 09:40:37 +08:00

675 lines
26 KiB
C#

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
{
/// <summary>
/// 日历控件,不含月份和年份选择
/// </summary>
[DefaultEvent("OnDateTimeChanged")]
[Description("农历日历控件")]
[ToolboxBitmap(typeof(System.Windows.Forms.MonthCalendar))]
public partial class PaChinaCalendar : UserControl
{
/// <summary>
///
/// </summary>
public PaChinaCalendar() : base()
{
InitializeComponent();
this.DoubleBuffered = true;
}
/// <summary>
/// 选择的日期变化时激发
/// </summary>
[Description("选择的日期变化时激发")]
public event EventHandler OnDateTimeChanged;
private int _itemSize = 80;
/// <summary>
/// 单项大小
/// </summary>
[Description("单项大小")]
public int ItemSize
{
get
{
return _itemSize;
}
set
{
if (_itemSize == value) { return; }
_itemSize =value;
this.Invalidate();
}
}
private string holiday_folder = ".\\SysDb\\Holidays";
/// <summary>
/// 放假数据表
/// </summary>
public string HolidayFolder
{
get
{
return holiday_folder;
}
set
{
if (holiday_folder == value) { return; }
holiday_folder = value;
this.Invalidate();
}
}
private DateTime _DateTime = DateTime.Now;
/// <summary>
/// 当前选择的时间
/// </summary>
[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);
/// <summary>
/// 阳历天字体
/// </summary>
[Description("阳历天字体")]
public Font DayFont
{
get
{
return _DayFont;
}
set
{
if (_DayFont == value) { return; }
_DayFont = value;
this.Invalidate();
}
}
private Font _ChinaDayFont = new Font("微软雅黑", 10);
/// <summary>
/// 农历天字体
/// </summary>
[Description("农历天字体")]
public Font ChinaDayFont
{
get
{
return _ChinaDayFont;
}
set
{
if (_ChinaDayFont == value) { return; }
_ChinaDayFont = value;
this.Invalidate();
}
}
private int _HeaderHeight = 30;
/// <summary>
/// 标头高度(星期高度)
/// </summary>
[Description("标头高度(星期高度)")]
public int HeaderHeight
{
get
{
return _HeaderHeight;
}
set
{
if (_HeaderHeight == value) { return; }
_HeaderHeight = value;
this.Invalidate();
}
}
private int _CellSpace = 1;
/// <summary>
/// 列间距
/// </summary>
[Description("列间距")]
public int CellSpace
{
get
{
return _CellSpace;
}
set
{
if (_CellSpace == value) { return; }
_CellSpace = value;
this.Invalidate();
}
}
private int _RowSpace = 1;
/// <summary>
/// 行间距
/// </summary>
[Description("行间距")]
public int RowSpace
{
get
{
return _RowSpace;
}
set
{
if (_RowSpace == value) { return; }
_RowSpace = value;
this.Invalidate();
}
}
private Font _HeaderFont = new Font("微软雅黑",11);
/// <summary>
/// 星期字体
/// </summary>
[Description("星期字体")]
public Font HeaderFont
{
get
{
return _HeaderFont;
}
set
{
if (_HeaderFont == value) { return; }
_HeaderFont = value;
this.Invalidate();
}
}
private Color _HolidayForeColor = Color.Orange;
/// <summary>
/// 节日颜色
/// </summary>
[Description("节日颜色")]
public Color HolidayForeColor
{
get
{
return _HolidayForeColor;
}
set
{
if (_HolidayForeColor == value) { return; }
_HolidayForeColor = value;
this.Invalidate();
}
}
private int _Mode = 0;
/// <summary>
/// 模式(0表示日模式,1表示月份展示模式,2表示年份展示模式)
/// </summary>
[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;
/// <summary>
/// 左边距
/// </summary>
[Description("左边距")]
public int PaddingLeft
{
get
{
return _PaddingLeft;
}
set
{
if (_PaddingLeft == value) { return; }
_PaddingLeft = value;
this.Invalidate();
}
}
private int _PaddingTop = 0;
/// <summary>
/// 顶部边距
/// </summary>
[Description("顶部边距")]
public int PaddingTop
{
get
{
return _PaddingTop;
}
set
{
if (_PaddingTop == value) { return; }
_PaddingTop = value;
this.Invalidate();
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
{
this.Invalidate();
base.OnSizeChanged(e);
}
/// <summary>
/// 单击某个日期事件
/// </summary>
public event ClickItemHandler OnClickItem;
/// <summary>
///
/// </summary>
/// <param name="e"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="keyData"></param>
/// <returns></returns>
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);
}
/// <summary>
/// 是否处于设计模式
/// </summary>
/// <returns></returns>
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<DayItem> list_rect = [];
private readonly rySafe.UsingLock<object> lock_dayitem=new rySafe.UsingLock<object>();
/// <summary>
///
/// </summary>
/// <param name="e"></param>
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
{
/// <summary>
/// 0表示日模式,1表示月份展示模式,2表示年份展示模式
/// </summary>
public int Mode { get; set; } = 0;
public DateTime Date { get; set; } = DateTime.MinValue;
/// <summary>
/// 显示的位置
/// </summary>
public Rectangle Rect { get; set; }
public string DayText { get; set; } = "";
public string ChinaDayText { get; set; } = "";
/// <summary>
/// 是否是节假日
/// </summary>
public bool IsHoliday { get; set; } = false;
/// <summary>
/// 休息状态,1为休息,-1为上班
/// </summary>
public int RestState { get; set; } = 0;
}
}
}