Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Customizable MonthCalendar Type Control: Part 2

0.00/5 (No votes)
16 Nov 2005 1  
A truly customizable MonthCalendar type control.

Sample Image

Screenshot showing appointment details.

Sample Image

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here