65.9K
CodeProject 正在变化。 阅读更多。
Home

可自定义的 MonthCalendar 类型控件:第一部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.21/5 (17投票s)

2005年5月26日

4分钟阅读

viewsIcon

186517

downloadIcon

13846

一个真正可自定义的MonthCalendar类型控件。

Sample Image

引言

作为创建CRM软件包的团队成员,我负责项目的用户界面部分。所有CRM软件都需要约会日历。我最初选择使用MonthCalendar控件来允许用户选择约会日期。创建约会后,我将新日期添加到MonthCalendar控件的BoldedDates数组中,以指示该日期有约会。我对MonthCalendar控件在外观方面缺乏自定义选项感到沮丧。与市场部门(主要用户)的第一次会议中,他们要求将粗体日期更改为不同的颜色,并显示更完整的月份视图,其中显示每一天约会的缩写。月份视图还需要能够打印。

我决定创建自己的MonthCalendar类型用户控件,该控件可用于选择日期并显示整个月份的较大尺寸以及约会缩写。这是我在.NET中创建的第一个Windows控件,我在VB5和VB6中有七年的Windows经验,但我主要是在过去两年中使用C#进行ASP.NET应用程序开发,使用GDI+创建在线图表。

我把开发分成了两部分。

第一部分。– 创建我自己的MonthCalendar类型控件,其基本功能与.NET MonthCalendar相同,并且能够自定义所有外观方面。

第二部分。– 实现完整的月份视图,包括约会缩写和打印功能。

本文仅涵盖第一部分。

背景

该控件包含两个Button、一个Label和一个PictureBoxButton用于移动到下一个或上一个月份。Label显示月份和年份,而PictureBox显示实际的日历。日历在PictureBoxPaint事件中绘制。该控件公开了一个额外的事件,SelectedDateChanged

可以更改以下属性

  • 活动月份背景颜色。
  • 非活动月份背景颜色。
  • 标题背景颜色。
  • 选中日期背景颜色。
  • 选中日期字体颜色。
  • 粗体日期字体颜色。
  • 网格颜色。
  • 控件背景颜色。
  • 粗体日期使用的字体。
  • 非粗体日期使用的字体。

可以启用或禁用以下属性

  • 显示上一个和下一个按钮。
  • 绘制网格。
  • 在活动月份显示月份名称。
  • 缩写标题中的星期几名称。
  • 将周末日期显示为较深颜色。

测试应用程序演示了更改一些属性,并将SelectedDate显示为窗体的标题。

使用代码

代码的整个结构基于一个7 x 6的网格,我用它来显示日历。一个7 x 6的整数数组保存关于网格中每个日期的数据,一个数组用于日期数字,一个数组用于月份数字。这些值决定了网格的每个单元格应该如何绘制。PictureBox被分成一个矩形数组,这些矩形将在Paint事件中使用。

该控件可以在任何使用标准MonthCalendar控件的地方使用,它接受一个要加粗的日期数组。它可以调整大小以适应可用空间。

用适当的日期数据填充数组的函数是这一阶段最有趣的部分。请参见源代码中的FillDates()

关注点

该控件能够将周末日期显示为比本月其他日期略深的颜色。为此,我根据选择的颜色创建一个新颜色,并使用该颜色作为画笔。在这种情况下,每个RGB属性都是原始颜色的80%。

brushActive = new SolidBrush(p_ActiveMonthColor);
ActiveDarker = Color.FromArgb((int)(p_ActiveMonthColor.R*0.8), 
               (int)(p_ActiveMonthColor.G*0.8), 
               (int)(p_ActiveMonthColor.B*0.8));
brushActiveDarker = new SolidBrush(ActiveDarker);

该控件公开了一个额外的事件,SelectedDateChanged。当选定日期更改时,将触发此事件。为此,我创建一个类来保存事件数据。此类必须派生自EventArgs

using System;

namespace MPK_Calendar
{
    /// <summary>
    /// Event argument class.
    /// </summary>
    public class SelectedDateChangedEventArgs:EventArgs
    {
        private DateTime pSelectedDate;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="dateSelected">Date </param>
        public SelectedDateChangedEventArgs(DateTime dateSelected)
        {
            pSelectedDate = dateSelected;
        }

        /// <summary>
        /// The selected date.
        /// </summary>
        public DateTime SelectedDate
        {
            get
            {
                return pSelectedDate;
            }
        }

    }
}

声明事件的委托

public delegate void SelectedDateChangedEventHandler(object sender, 
                                     SelectedDateChangedEventArgs e);

提供一个public事件成员

#region Custom events
/// <summary>
/// Event handler definition
/// </summary>
public event SelectedDateChangedEventHandler SelectedDateChanged;

创建一个protected函数来引发事件

protected virtual void 
    OnSelectedDateChanged(SelectedDateChangedEventArgs eventArgs)
{
    if(SelectedDateChanged!=null)
    {
        SelectedDateChanged(this,eventArgs);
    }
}
#endregion Custom events

最后在演示应用程序的形式中使用该事件

private void mpK_Calendar1_SelectedDateChanged_1(object sender, 
                  MPK_Calendar.SelectedDateChangedEventArgs e)
{
    this.Text = e.SelectedDate.ToShortDateString();
}

众所周知,公共属性可以在属性编辑器中编辑。属性定义上方的两行代码允许我指定一个类别和一个说明,以便在属性编辑器中使用。

[Description("Grid color.")]
[Category("MPK_Calendar")]
public Color GridColor
{
    get
    {
        return p_GridColor;
    }
    set
    {
        pGridColor=value;
        this.picMPK_Cal.Invalidate();
    }
}

历史

  • 2005年11月8日 - 修复了更改月份时出现的错误。我还更改了日期信息的存储方式。
© . All rights reserved.