C# 自定义日历控件

效果预览:
显示一周日期:

 

 下拉先展示一月日期

点击"<" 、">"按钮切换月份

具体代码:
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);

        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值