Click here to Skip to main content
Click here to Skip to main content

Customizable MonthCalendar Type Control: Part 2

, 16 Nov 2005
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Michael Krisky
Web Developer
United States United States
I've been developing software since 1995, using VB5, VB6, ASP, Javascript and most recently C# for ASP.NET and Windows. Current interests include embedded systems for robotics with the BASIC Stamp microcontroller from Parallax and the Brainstem module from Acroname.

Comments and Discussions

 
GeneralCustomizable MonthCalendar Pinmemberzaferms28-Mar-11 3:15 
GeneralImportant Pinmembereman.tabbara1-Dec-09 20:26 
GeneralNice but... Pinmemberchmod222211-Jul-07 0:52 
GeneralBolded Dates PinmemberHomerGER20-Apr-07 11:42 
GeneralPrintPreviewCalendar() modifies the DOW header sizing PinmemberBurt Crockett20-Jul-06 11:15 
Great tool/article! I made one minor adjustment.
 
I changed the print preview to perserve the original Day of the Week header sizing...
 
public void PrintPreviewCalendar()
{
//Save the original Day of the Week sizing
Rectangle[] SaveRectDays = new Rectangle[7];
SaveRectDays = rectDays;
 
PrintPreviewDialog ppdlg = new PrintPreviewDialog();
PrintDocument pd = new PrintDocument();
pd.PrintPage+=new PrintPageEventHandler(pd_PrintPage);
pd.DefaultPageSettings.Landscape=true;
ppdlg.Document = pd;
ppdlg.ShowDialog();
 
//Restore the original Day of the Week sizing
rectDays = SaveRectDays;
 
}
Questionhow to change maxselectionnumber Pinmemberjabulino24-Nov-05 6:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 16 Nov 2005
Article Copyright 2005 by Michael Krisky
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid