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;
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:
ContextMenu contextMenu1 = new ContextMenu();
int intApptCtr=0;
contextMenu1.MenuItems.Clear();
if(e.Button==MouseButtons.Right)
{
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)
{
contextMenu1.Show(this,new Point(e.X,e.Y));
}
}
else
{
}
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.
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