效果预览:
显示一周日期:
下拉先展示一月日期
点击"<" 、">"按钮切换月份
具体代码:
form 窗体:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TimeControl
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
initControl();
}
/// <summary>
/// 自定义控件
/// </summary>
private CircleLabelControl selectCircLabel = new CircleLabelControl();
/// <summary>
/// 选择日期
/// </summary>
private DateTime selectDate = DateTime.Now;
/// <summary>
/// 日历显示模式:true显示一周, false显示一个月
/// </summary>
private bool isWeekMode = true;
/// <summary>
/// 用于存储界面显示的日期集合
/// </summary>
private Dictionary<Point , DateTime> timeDic = new Dictionary<Point, DateTime>();
/// <summary>
/// 图片位置,根据自己实际更换
/// </summary>
private string show = @"G:\emrVS01\TimeControl\TimeControl\Resoutces\展开.jpg";
/// <summary>
/// 图片位置,根据自己实际更换
/// </summary>
private string fold = @"G:\\emrVS01\\TimeControl\\TimeControl\\Resoutces\\收起.jpg";
#region 方法
/// <summary>
/// 初始化
/// </summary>
private void initControl()
{
this.StartPosition = FormStartPosition.CenterParent;
this.time.SelectionStart = DateTime.Now;
this.time.FirstDayOfWeek = Day.Sunday;
this.time.MaxSelectionCount = 7;
this.lbTimeShow.Text = DateTime.Now.ToString("yyyy | MM.dd");
this.picMode.Click += pictureBox1_Click;
this.lbLeft.Click += label3_Click;
this.lbRight.Click += label4_Click;
picMode.ImageLocation = show;
DateTime dateNow = DateTime.Now;
DayOfWeek week = dateNow.DayOfWeek;
setDate(dateNow, week, 0);
foreach (KeyValuePair<Point, DateTime> point in timeDic)
{
if (point.Value == Convert.ToDateTime(selectDate.ToString("yyyy-MM-dd")))
{
foreach (Control control in this.pnlDate.Controls)
{
if (control.Location == point.Key)
{
CircleLabelControl circleLabel = (CircleLabelControl)control;
setSelectCircLabel(circleLabel);
break;
}
}
}
}
}
/// <summary>
/// 设置日期方法
/// </summary>
/// <param name="date">传入时间</param>
/// <param name="week">传入时间属于星期几</param>
/// <param name="y">时间y坐标</param>
private void setDate(DateTime date, DayOfWeek week, int y)
{
DateTime dateTimeDic = DateTime.Now;
for (int i = 0; i <= 7; i++)
{
CircleLabelControl circleLabel = new CircleLabelControl();
circleLabel.Location = new Point(6 + i * 42, 2 + y * 26);
Brush backColor = Brushes.WhiteSmoke;
Brush textColor = Brushes.Black;
circleLabel.Text = getDateString(i, ref backColor, ref textColor, date, week, y, ref dateTimeDic);
circleLabel.BackColor = backColor;
circleLabel.TextColor = textColor;
circleLabel.Name = $"circleLabel + {i} + {y}";
circleLabel.Size = new Size(25, 25);
circleLabel.Font = new System.Drawing.Font("Arial", 10.5f, FontStyle.Regular);
circleLabel.Click += circleLabel_Click;
this.pnlDate.Controls.Add(circleLabel);
timeDic.Add(circleLabel.Location, dateTimeDic);
}
}
/// <summary>
/// 获取日期时间
/// </summary>
/// <param name="i">时间x坐标</param>
/// <param name="backColor">时间点背景颜色</param>
/// <param name="textColor">时间点文字颜色</param>
/// <param name="dateNow">传入时间</param>
/// <param name="week">传入时间属于星期几</param>
/// <param name="y">时间y坐标</param>
/// <param name="dateTimeDic">返回时间</param>
/// <returns></returns>
private string getDateString(int i, ref Brush backColor, ref Brush textColor, DateTime dateNow, DayOfWeek week, int y, ref DateTime dateTimeDic)
{
string date = string.Empty;
switch (week)
{
case DayOfWeek.Sunday:
date = dateNow.AddDays(-6 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-6 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Monday:
date = dateNow.AddDays(0 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(0 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Tuesday:
date = dateNow.AddDays(-1 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-1 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Wednesday:
date = dateNow.AddDays(-2 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-2 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Thursday:
date = dateNow.AddDays(-3 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-3 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Friday:
date = dateNow.AddDays(-4 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-4 + i).ToString("yyyy-MM-dd"));
break;
case DayOfWeek.Saturday:
date = dateNow.AddDays(-5 + i).ToString("dd");
dateTimeDic = Convert.ToDateTime(dateNow.AddDays(-5 + i).ToString("yyyy-MM-dd"));
break;
}
if (dateTimeDic.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd"))
{
//backColor = Brushes.RoyalBlue;
textColor = Brushes.Blue;
date = "今";
}
if (dateTimeDic.ToString("yyyy - MM") != selectDate.ToString("yyyy - MM") && !isWeekMode)
{
textColor = Brushes.Gray;
}
return date;
}
/// <summary>
/// 获取选中控件时间
/// </summary>
/// <returns></returns>
private DateTime getSelectDateTime()
{
DateTime date = DateTime.Now;
foreach (KeyValuePair<Point, DateTime> point in timeDic)
{
if (point.Key == selectCircLabel.Location)
{
date = point.Value;
}
}
selectDate = date;
return date;
}
/// <summary>
/// 选中时间点
/// </summary>
/// <param name="circleLabelControl">选中控件</param>
private void setSelectCircLabel(CircleLabelControl circleLabelControl)
{
selectCircLabel = circleLabelControl;
selectDate = getSelectDateTime();
this.lbTimeShow.Text = selectDate.ToString("yyyy | MM") + "." + selectDate.ToString("dd");
if (circleLabelControl.TextColor == Brushes.Gray && !isWeekMode)
{
setPicture();
return;
}
circleLabelControl.BackColor = Brushes.RoyalBlue;
circleLabelControl.TextColor = Brushes.White;
circleLabelControl.Font = new System.Drawing.Font("Arial", 10.5f, FontStyle.Bold);
string text = circleLabelControl.Text == "今" ? DateTime.Now.ToString("dd") : circleLabelControl.Text;
foreach (Control control in this.pnlDate.Controls)
{
Type type = control.GetType();
if (type.Name.ToString() == "CircleLabelControl" && control.Name != circleLabelControl.Name)
{
CircleLabelControl circle = control as CircleLabelControl;
circle.BackColor = Brushes.WhiteSmoke;
if (circle.TextColor != Brushes.Gray)
{
circle.TextColor = circle.Text == "今" ? Brushes.Blue : Brushes.Black;
}
circle.Font = new System.Drawing.Font("Arial", 10.5f, FontStyle.Regular);
}
}
}
/// <summary>
/// 下拉、收起图片方法
/// </summary>
private void setPicture()
{
if (picMode.ImageLocation == fold)
{
DateTime dateTime = Convert.ToDateTime(getSelectDateTime().ToString("yyyy-MM-01"));
DayOfWeek dayOfWeek = dateTime.DayOfWeek;
getDateValue(dateTime, dayOfWeek);
return;
}
this.pnlDate.Controls.Clear();
this.pnlDate.Size = new Size(291, 26);
DateTime dateNow = selectDate;
DayOfWeek week = dateNow.DayOfWeek;
timeDic = new Dictionary<Point, DateTime>();
setDate(dateNow, week, 0);
foreach (KeyValuePair<Point, DateTime> point in timeDic)
{
if (point.Value == Convert.ToDateTime(selectDate.ToString("yyyy-MM-dd")))
{
foreach (Control control in this.pnlDate.Controls)
{
if (control.Location == point.Key)
{
CircleLabelControl circleLabel = (CircleLabelControl)control;
setSelectCircLabel(circleLabel);
break;
}
}
}
}
}
/// <summary>
/// 获取时间
/// </summary>
/// <param name="dateTime">传入时间</param>
/// <param name="dayOfWeek">传入星期</param>
private void getDateValue(DateTime dateTime, DayOfWeek dayOfWeek)
{
int daysInMonth = DateTime.DaysInMonth(dateTime.Year, dateTime.Month);
int num = 0;
if (daysInMonth <= 30 && dayOfWeek == DayOfWeek.Sunday)
{
num = 6;
}
if (daysInMonth <= 30 && dayOfWeek > DayOfWeek.Sunday)
{
num = 5;
}
if (daysInMonth > 30 && (dayOfWeek > DayOfWeek.Sunday && dayOfWeek <= DayOfWeek.Friday))
{
num = 5;
}
if (daysInMonth > 30 && (dayOfWeek == DayOfWeek.Sunday || dayOfWeek > DayOfWeek.Friday))
{
num = 6;
}
this.pnlDate.Size = new Size(291, 3 + num * 26);
this.pnlDate.Controls.Clear();
// 使用DaysInMonth获取当前月份的天数
timeDic = new Dictionary<Point, DateTime>();
for (int j = 0; j < num; j++)
{
if (j > 0)
{
dateTime = dateTime.AddDays(7);
dayOfWeek = dateTime.DayOfWeek;
}
setDate(dateTime, dayOfWeek, j);
}
foreach (KeyValuePair<Point, DateTime> point in timeDic)
{
if (point.Value == Convert.ToDateTime(selectDate.ToString("yyyy-MM-dd")))
{
foreach (Control control in this.pnlDate.Controls)
{
if (control.Location == point.Key)
{
CircleLabelControl circleLabel = (CircleLabelControl)control;
setSelectCircLabel(circleLabel);
break;
}
}
}
}
}
#endregion
#region 事件
/// <summary>
/// 日期选择事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void circleLabel_Click(object sender , EventArgs e)
{
CircleLabelControl circleLabelControl = sender as CircleLabelControl;
setSelectCircLabel(circleLabelControl);
}
/// <summary>
/// 下拉展开、收起事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void pictureBox1_Click(object sender ,EventArgs e)
{
isWeekMode = picMode.ImageLocation == show ? false : true;
picMode.ImageLocation = picMode.ImageLocation == show ? fold : show;
setPicture();
}
/// <summary>
/// 向左lable按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label3_Click(object sender, EventArgs e)
{
DateTime dateTime = getSelectDateTime();
if (!isWeekMode)
{
dateTime = Convert.ToDateTime(dateTime.AddMonths(-1).ToString("yyyy-MM-01"));
selectDate = dateTime;
DayOfWeek monthWeek = dateTime.DayOfWeek;
timeDic = new Dictionary<Point, DateTime>();
this.pnlDate.Controls.Clear();
getDateValue(dateTime, monthWeek);
return;
}
dateTime = dateTime.AddDays(-7);
DayOfWeek week = dateTime.DayOfWeek;
timeDic = new Dictionary<Point, DateTime>();
this.pnlDate.Controls.Clear();
setDate(dateTime, week, 0);
foreach (Control control in this.pnlDate.Controls)
{
if (control.Location == timeDic.FirstOrDefault().Key)
{
CircleLabelControl circleLabel = (CircleLabelControl)control;
setSelectCircLabel(circleLabel);
break;
}
}
}
/// <summary>
/// 向右lable按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label4_Click(object sender ,EventArgs e )
{
DateTime dateTime = getSelectDateTime();
if (!isWeekMode)
{
dateTime = Convert.ToDateTime(dateTime.AddMonths(1).ToString("yyyy-MM-01"));
selectDate = dateTime;
DayOfWeek monthWeek = dateTime.DayOfWeek;
timeDic = new Dictionary<Point, DateTime>();
this.pnlDate.Controls.Clear();
getDateValue(dateTime, monthWeek);
return;
}
dateTime = dateTime.AddDays(7);
DayOfWeek week = dateTime.DayOfWeek;
timeDic = new Dictionary<Point, DateTime>();
this.pnlDate.Controls.Clear();
setDate(dateTime, week, 0);
foreach (Control control in this.pnlDate.Controls)
{
if (control.Location == timeDic.FirstOrDefault().Key)
{
CircleLabelControl circleLabel = (CircleLabelControl)control;
setSelectCircLabel(circleLabel);
break;
}
}
}
#endregion
}
}
自定义圆形时间点控件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TimeControl
{
public partial class CircleLabelControl : Control
{
public CircleLabelControl()
{
}
private string _text = "0";
private Font _font = new Font("Arial", 10.5f, FontStyle.Bold);
private Brush _backColor = Brushes.Red;
private Brush _TextColor = Brushes.White;
public override string Text
{
get { return _text; }
set
{
_text = value;
Invalidate(); // 当文本更改时,触发重绘
}
}
public override Font Font
{
get { return _font; }
set
{
_font = value;
Invalidate(); // 当字体更改时,触发重绘
}
}
public Brush TextColor
{
get { return _TextColor; }
set
{
_TextColor = value;
Invalidate(); // 当字体更改时,触发重绘
}
}
public Brush BackColor
{
get { return _backColor; }
set
{
_backColor = value;
Invalidate(); // 当字体更改时,触发重绘
}
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
// 绘制圆形背景(可选)
pe.Graphics.FillEllipse(BackColor, 0, 0, Width, Height);
// 计算文本的位置以在圆形中居中
StringFormat sf = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
// 绘制文本
pe.Graphics.DrawString(Text, Font, TextColor, new RectangleF(0, 0, Width, Height), sf);
}
}
}