As part of a team creating a CRM software package, I am in charge of the user interface portion of the project. A requisite part of all CRM software is an appointment calendar. I initially chose to use the
MonthCalendar control to allow the user to select the date of the appointment. After they create the appointment, I add the new date to the
BoldedDates array of the
MonthCalendar control to designate an appointment on that date. I was frustrated with the lack of customization available to the
MonthCalendar control with regards to appearance. The first meeting with our marketing department (the primary users) yielded requests to make the bolded dates a different color and a more complete month view showing an abbreviation of the appointments for each day. The month view would also need to be printed.
I decided to create my own
MonthCalendar type user control that could be used to select a date and display a larger size of the entire month with appointment abbreviations. This is my first Windows control in .NET, I have seven years Windows experience in VB5 and VB6 but I have mainly spent the last 2 years using C# in ASP.NET applications creating online charts using GDI+.
I broke the development up into two parts.
Part 1. – Create my own
MonthCalendar type control with the same basic functionality as the .NET
MonthCalendar along with the ability to customize all aspects of visual appearance.
Part 2. – Implement the full month view with appointment abbreviations and print functionality.
This article only covers part 1.
The control consists of two
Label, and one
Buttons are used to move to the next or previous month. The
Label displays the month and year while the
PictureBox displays the actual calendar. The calendar is drawn in the
Paint event of the
PictureBox. The control exposes one additional event,
The following properties may be changed:
- Active month background color.
- Inactive month background color.
- Header background color.
- Selected date background color.
- Selected date font color.
- Bolded date font color.
- Grid color.
- Control background color.
- Font used for bolded dates.
- Font used for not bolded dates.
The following properties may be toggled on or off:
- Display previous and next buttons.
- Draw the grid.
- Display month name in active month.
- Abbreviate day name in header.
- Display weekend days darker.
The test application demonstrates changing a few of the properties and displays the
SelectedDate as the title of the form.
Using the code
The entire structure of the code is based on a 7 x 6 grid I use to display the calendar. A 7 x 6 array of integer arrays hold data about each day represented in the grid, one array for the day number and one for the month number. These values determine how each cell of the grid should be drawn. The
PictureBox is divided into an array of rectangles that will be used in the
The control may be used anywhere a standard
MonthCalendar control would be used and it accepts an array of dates to be bolded. It may be sized to fit the space available.
The function that fills the arrays with the appropriate date data was the most interesting part of this phase. See
FillDates() in the source code.
Points of Interest
The control has the ability to display the weekend days slightly darker than the rest of the days of the month. To accomplish this, I create a new color based on the one chosen, and use that color for the brush. In this case, each of the RGB attributes are 80% of the original.
brushActive = new SolidBrush(p_ActiveMonthColor);
ActiveDarker = Color.FromArgb((int)(p_ActiveMonthColor.R*0.8),
brushActiveDarker = new SolidBrush(ActiveDarker);
The control exposes one additional event,
SelectedDateChanged. This event is fired when the selected date is changed. To do this, I create a class to hold event data. This class must be derived from
public class SelectedDateChangedEventArgs:EventArgs
private DateTime pSelectedDate;
public SelectedDateChangedEventArgs(DateTime dateSelected)
pSelectedDate = dateSelected;
public DateTime SelectedDate
Declare the delegate of the event:
public delegate void SelectedDateChangedEventHandler(object sender,
public event member:
#region Custom events
public event SelectedDateChangedEventHandler SelectedDateChanged;
protected function that raises the event:
protected virtual void
#endregion Custom events
Finally consume the event in the form of the demo application:
private void mpK_Calendar1_SelectedDateChanged_1(object sender,
this.Text = e.SelectedDate.ToShortDateString();
Everyone knows that public properties can be edited in the properties editor. The two lines above the property definition allowed me to specify a category and a description for use in the property editor:
public Color GridColor
- November 8, 2005 - Fixed a bug that occurs when the month is changed. I also changed the way the date information is stored.