Customizable MonthCalendar Type Control: Part 2






4.43/5 (7 votes)
Nov 16, 2005
2 min read

80931

3312
A truly customizable MonthCalendar type control.
Screenshot showing appointment details.
Portion of the print preview window.
Introduction
This is the second part of my article: Customizable MonthCalendar Type Control. The new capabilities added to the MonthCalendar
control include:
- Add appointments to the control. This will take the place of the
BoldedDates
array. Each appointment will contain a date, starting and ending times and a description. The date will appear bolded in the calendar; to view appointment info, right-click on the date. - Print capability for month calendar. The month grid and up to four appointments for each day will be printed.
- Two new classes have been added to the calendar control, an appointment class and an appointment collection class. When the calendar is drawn, I check to see if any of the appointments match the date being drawn. If it does the date will be bolded. I wanted to display the appointment data without adding any other components to the calendar. To accomplish this, I display the appointment data in a context menu when the right mouse is pressed.
- The process to print the calendar is very similar to the
Paint
routine, with the addition of four rectangles where the appointment information is drawn.
Background
See part 1 of this article: Customizable MonthCalendar Type Control.
Using the code
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.
Creating appointments:
private void Form1_Load(object sender, System.EventArgs e)
{
mpK_Calendar1.SelectedDateChanged+= new
SelectedDateChangedEventHandler(mpK_Calendar1_SelectedDateChanged);
mpK_Calendar1.SelectedDate=DateTime.Now;
//part 2
//At this point, the assumption is that
//appointments are added in chronological order
mpK_Calendar1.Appointments.Add(new DateTime(2005,11,1,6,0,0),
new DateTime(2005,11,1,7,0,0),"TEST DESCRIPTION");
mpK_Calendar1.Appointments.Add(new DateTime(2005,11,1,8,0,0),
new DateTime(2005,11,1,9,0,0),"TEST DESCRIPTION");
mpK_Calendar1.Appointments.Add(new DateTime(2005,11,1,10,0,0),
new DateTime(2005,11,1,11,0,0),"TEST DESCRIPTION");
}
New appointment and appointment collection classes:
public class clsAppt
{
public DateTime ApptStart;
public DateTime ApptEnd;
public string strDesc;
public clsAppt(DateTime ApptStartIn,
DateTime ApptEndIn,string strDescIn)
{
ApptStart = ApptStartIn;
ApptEnd = ApptEndIn;
strDesc = strDescIn;
}
}
public class clsApptColl:System.Collections.CollectionBase
{
public clsApptColl()
{
}
public void Add(clsAppt Appt)
{
List.Add(Appt);
}
public void Add(DateTime ApptStartIn,
DateTime ApptEndIn,string strDescIn)
{
List.Add(new clsAppt(ApptStartIn,ApptEndIn,strDescIn));
}
public void Remove(int intIndex)
{
if(intIndex>-1 && intIndex<List.Count)
{
List.RemoveAt(intIndex);
}
}
public clsAppt Item(int intIndex)
{
return (clsAppt) List[intIndex];
}
public int ListCount()
{
return List.Count;
}
}
Points of Interest
This is the code to dynamically create the context menu when the right-mouse is clicked:
//part 2
//A context menu is used to display the full details of each appointment.
//Based on the X,Y coordinates of the mouse,
//check to see if there are any appointments to display.
//dynamically create context menu
ContextMenu contextMenu1 = new ContextMenu();
//counter
int intApptCtr=0;
contextMenu1.MenuItems.Clear();
if(e.Button==MouseButtons.Right)//right mouse
{
for(int k=0;k<Appointments.ListCount();k++)
{
if(Appointments.Item(k).ApptStart.Date==this.SelectedDate)
{
if(intApptCtr>0)
{
contextMenu1.MenuItems.Add(contextMenu1.MenuItems.Count,
new MenuItem("-"));
}
contextMenu1.MenuItems.Add(contextMenu1.MenuItems.Count,
new MenuItem("Date: " +
Appointments.Item(k).ApptStart.Date.ToLongDateString()));
contextMenu1.MenuItems.Add(contextMenu1.MenuItems.Count,
new MenuItem("Time: " +
Appointments.Item(k).ApptStart.TimeOfDay +
" - " + Appointments.Item(k).ApptEnd.TimeOfDay));
contextMenu1.MenuItems.Add(contextMenu1.MenuItems.Count,
new MenuItem("Subject: " +
Appointments.Item(k).strDesc));
intApptCtr++;
}
}
if(intApptCtr>0)
{
//show context menu
contextMenu1.Show(this,new Point(e.X,e.Y));
}
}
else//left mouse
{
}
//part 2
When using GDI+ to paint forms or for printing, here are a couple of items I find useful.
When drawing text, I prefer to draw the text into a rectangle and use a StringFormat
object to properly layout the text.
//string format for calendar body
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;
sf.Trimming = StringTrimming.EllipsisCharacter;
The Alignment
property determines the left to right placement of the text within the rectangle. The LineAlignment
property determines the up and down placement within the rectangle. The Trimming
property determines what will happen if the text is too long for the rectangle.
If you need a standard color brush, you can create one:
new SolidBrush(Color.Black);
or use one from the Brushes
class:
Brushes.Black