Click here to Skip to main content
15,861,168 members
Articles / Desktop Programming / MFC
Article

MS Outlook style miniature calendar control

Rate me:
Please Sign up or sign in to vote.
4.98/5 (37 votes)
28 Jan 2002CPOL7 min read 509.1K   6.8K   175   77
A custom CWnd derived control which simulates the functionality of the MS Outlook mini calendar control.

What is this Control?

This is an attempt to reproduce the functionality of the MS Outlook miniature calendar control as it appears in the date picker control  and as it appears in the day-view scheduler.  It supports many of the same features as the MS control.

Below are some screen shots of the control.

Image 1

(Standard 1 month view demonstrating Today and None buttons)

Image 2

(12 month view)

Image 3

(8 month view demonstrating the header-picker pop up)

Image 4

(4 month view demonstrating multi-select)

What can this Control do?

  • Support for 3d border similar to MS outlooks (optional)
  • Support for Today and/or a None button. (both optional)
  • Supports different font for header, day of week row, day numbers and special day numbers.
  • Supports highlighting today's date. (Optional)
  • Supports for N rows and N columns. (see screen shots)
  • Single or multi-select.  (Multi-select works across months)
  • Multi-select works across months.
  • Support for special days highlighting.  (See screen shots)
  • Support for automatic font size selection based on screen resolution, number of rows/columns and size of parent window.
  • Header date picker popup list. (See screen shot)
  • Multi-select can be limited to a maximum selection of X # of continuous days.
  • Displays a 6 week calendar when in 1 row, 1 column is set and displays days preceding the beginning on the upper-left cell and days following the end on the lower-right when more than 1 row or 1 column is set.

How does this control work?

This control consists of a CWnd derived class named CFPSMiniCalendarCtrl and numerous support classes.  Several available window styles control how the control will appear to the user.  The numbers of rows and columns can be specified with a simple method call.  The fonts can also be customized through method calls.  

Window Styles

FMC_MULTISELECT Enable multi-select mode
FMC_NOHIGHLIGHTTODAY Disable highlighting of today's date
FMC_TODAYBUTTON Enable today button
FMC_NONEBUTTON Enable none button
FMC_AUTOSETTINGS Auto configures control based on rows/columns and size of parent
FMC_NO3DBORDER Disable custom 3d border
FMC_NOSHOWNONMONTHDAYS Disable display of non-month days.  Usually when displaying a single row/single column calendar the days in the preceding and following months which fit on the 6 week calendar are displayed in gray.  This option disables display of those days.

Methods of Importance

SetRowsAndColumns (int iRows, int iCols)
Sets the number of rows and columns the control will display.
SetCurrentMonthAndYear (int iMonth, int iYear)
Sets the month/year the control will display in the first row and column.  Other cells will progress from this date.
SetBackColor (COLORREF cColor)
Sets the background color for the control.  Defaults to GetSysColor(COLOR_WINDOW)
SetMaxSize (SIZE size)
If auto-configure settings is enabled, this method sets the maximum size the control can occupy.  You can use any SIZE you wish or one of two constants FMC_MAX_SIZE_NONE and FMC_MAX_SIZE_PARENT
SetMaxSelDays (int iValue)
If multi-select is enabled, this method sets the maximum number of continuous days that may be selected. You can use any positive value starting from 1, or you can use the constant FMC_NO_MAX_SEL_DAYS.
SetDefaultMinFontSize (int iValue)
If auto-configure is enabled, this sets the minimum font size the control can use to achieve a fit.  If it reaches the min font size and still does not fit, the control stops trying to auto-fit and uses this font size.  The internal default (if this method is not called) is 5.
SetDefaultFont (LPCTSTR lpszValue)
If auto-configure is enabled, sets the font name to use for the various options.  The internal default (if this method is not called) is "Tahoma"
SetHeaderFont (LPCTSTR lpszFont, int iSize, BOOL bBold, BOOL bItalic, BOOL bUnderline, COLORREF cColor)
Sets the font to be used by the header.  This header contains the month name and year number.
SetDaysOfWeekFont (LPCTSTR lpszFont, int iSize, BOOL bBold, BOOL bItalic, BOOL bUnderline, COLORREF cColor)
Sets the font to be used by the days-of-week header.  This header contains the days of week labels (S M T W T F S).
SetDaysFont (LPCTSTR lpszFont, int iSize, BOOL bBold, BOOL bItalic, BOOL bUnderline, COLORREF cColor)
Sets the font to be used by the day numbers.
SetSpecialDaysFont (LPCTSTR lpszFont, int iSize, BOOL bBold, BOOL bItalic, BOOL bUnderline, COLORREF cColor)
Sets the font to be used by the day numbers when the day is a "special" day.
GetDate Returns the data selected in the control.  Used when single-select is set.
GetDateSel (COleDateTime& dtBegin, COleDateTime& dtEnd)
Retrieves the date range selected when in multi-select mode.  Also works in single-select mode.
IsDateSelected (COleDateTime& dt)
Returns TRUE if the date specified is selected, otherwise returns FALSE.
ScrollLeft (int iCount)
Scrolls the month back the specified number of months.
ScrollRight (int iCount)
Scrolls the month forward the specified number of months.
SetSpecialDaysCallback (funcSPECIALDATE pValue)
The control uses a callback function so the containing application can provide information on special dates.  This function is used to set this callback function.  By default, there are no special dates.  
The format of this function is:
typedef BOOL (CALLBACK* funcSPECIALDATE)(COleDateTime&);

How to use this Control

The demonstration application provided with this article is an excellent example of how the control works and how to implement the control in your own applications.  Below are the basic steps to using the control.

  1. Add the "FPSMiniCalendarCtrl.h", "FPSMiniCalendarCtrl.cpp", "FPSMiniCalendarListCtrl.h" and "FPSMiniCalendarListCtrl.cpp" files to your project.
  2. Include "FPSMiniCalendarCtrl.h" in your "stdafx.h" file.  (You can also include it in each class header where you plan to use it.)
  3. In your classes .h file, decalre a member of type CFPSMiniCalendarCtrl. (See sample 1 below)
  4. In your classes .cpp file (the OnCreate, OnInitialUpdate or OnInitDialog functions will all work).  Call the Create function with the required styles and desired position for the control.  (See sample 2 below.)
  5. If needed, set the date selection by calling the SetDate or SetDateSel method.
  6. If needed, set the number of rows and columns desired by calling the SetRowsAndColumns method.
  7. If needed, set the special dates call back function required for your needs by calling the SetSpecialDaysCallback method.  
  8. If you are not using auto-configure, you should call the RedrawWindow method to insure the user is presented with the refreshed settings.
  9. You will probably also want to setup a notification message map in your class to be notified when the date selection changes.  (See sample 3 below.)

Using the Special Days Callback Function

The special days callback function is used so that the control can highlight (usually in bold) days which are special for some reason.  This may be holidays, scheduled appointments, etc.  The callback function must be defined as below.

BOOL CALLBACK IsSpecialDateCallback(COleDateTime &dt);

It can be either a global function or a static method of one of your classes.

The implementation should return FALSE if the given date is not special and TRUE if it is. 

NOTE: This function is called quite often so try not to perform any long running processes in this function.

SAMPLE 1 (modifications to .h file)

// .h file, inside your classes definition

CFPSMiniCalendarCtrl m_wndCalendar;

SAMPLE 2 (modifications to .cpp file, OnCreate function)

// .cpp file before any methods are implemented

#define WMID_CALENDAR   WM_USER+1

// .cpp file (OnCreate, OnInitialUpdate or OnInitDialog will all work OK)

m_wndCalendar.Create(NULL, NULL, WS_CHILD | WS_VISIBLE | FMC_MULTISELECT |
                                 FMC_AUTOSETTINGS | FMC_TODAYBUTTON |
                                 FMC_NONEBUTTON,
                     CalendarRect, this, WMID_CALENDAR);
m_wndCalendar.SetDate(COleDateTime::GetCurrentTime());  // optional
m_wndCalendar.SetRowsAndColumns(3,4);  // optional
m_wndCalendar.SetSpecialDaysCallback(IsSpecialDateCallback);  // optional

SAMPLE 3 (how to be notified of selection changes)

// ********************************************************
// in your classes .h file, locate the end of the message map function
// declaration look for DECALRE_MESSAGE_MAP()

// immediately before DECLARE_MESSAGE_MAP(), insert the following line

afx_msg void OnCalendarClick(NMHDR * pNotifyStruct, LRESULT * result );

// ********************************************************
// in your classes .cpp file, locate the end of the message map call area
// look for END_MESSAGE_MAP()

// immediately before END_MESSAGE_MAP(), insert the following line

ON_NOTIFY(NM_CLICK, WMID_CALENDAR, OnCalendarClick)

// ********************************************************
// in your classes .cpp file, move to the end of the file and add the
// following lines

void CYourClassName::OnCalendarClick(NMHDR * , LRESULT * )
{
    COleDateTime dtBegin;
    COleDateTime dtEnd;

    m_wndCalendar.GetDateSel(dtBegin, dtEnd);

    // TODO: Add your custom handler here
}

Notes

This code is not perfect and not suited for all situations but at least for my project it has been very well received (especially by the end users.)  I am working to implement this control as a picker for the date edit control I posted previously.  (Click here to see the date edit control.)

I would appreciate any comments you have to make regarding my implementation or code.  Thanks.

Updates

Jan 28, 2002 Thanks to Pierre MEINDRE for pointing out some international issues related to days-of-week names and the first day of the week also thanks for suggestion for option to disable display of non-month days in calendar view.  Also, thanks to Rainer Mangold for pointing out the correct method (presumably) for determining the first day of the week. 

CHANGES:
Added a SetDayOfWeekName and GetDayOfWeekName function so that the days-of-week header row will display correctly according to locale. 
Added a SetFirstDayOfWeek function to set the first day-of week to be displayed in the days of week header and in the days display area.
Added an option to enable/disable display of non-month days in the calendar.  There is now a new window style which can be set during creation and functions SetShowNoneMonthDay and GetShowNoneMonthDay.
Corrected a problem with the popup header-list where it was possible to highlight 2 items at a time.
Modified OnLButtonDown and OnMouseMove code so that NM_CLICK message is not sent for single-click mode calendar until the mouse button is released (ie. OnLButtonUp).  This better simulates the MS Outlook control.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow do I integrate this into outlook 2008 or use it as an add in? Pin
Terry.Fernandez9-Aug-09 6:08
Terry.Fernandez9-Aug-09 6:08 
Generaljust download it,thansk Pin
XKT31-Mar-09 16:49
XKT31-Mar-09 16:49 
GeneralThanks... Pin
Hans Dietrich17-Mar-09 21:32
mentorHans Dietrich17-Mar-09 21:32 
QuestionActiveX Implementation Pin
kurtrayner1-Aug-06 6:59
kurtrayner1-Aug-06 6:59 
GeneralDayPilot - Outlook-like calendar/scheduling control for ASP.NET (open-source) Pin
Dan Letecky28-Jun-06 10:35
Dan Letecky28-Jun-06 10:35 
Generalquick easy silly question Pin
c0d3m@n19-Mar-06 13:37
c0d3m@n19-Mar-06 13:37 
GeneralWow !!! Pin
jabulino11-Jan-06 1:07
jabulino11-Jan-06 1:07 
GeneralChoose previous year Pin
Stoil10-Jun-05 7:16
Stoil10-Jun-05 7:16 
GeneralSelection failure Pin
elmezouaghi21-Feb-05 4:09
elmezouaghi21-Feb-05 4:09 
GeneralRe: Selection failure Pin
elmezouaghi21-Feb-05 4:50
elmezouaghi21-Feb-05 4:50 
QuestionRe: Selection failure Pin
Gismow16-Jan-06 21:55
Gismow16-Jan-06 21:55 
GeneralI've finished random selection Pin
ectoplasm7-Nov-04 20:54
ectoplasm7-Nov-04 20:54 
GeneralI've finished random selection Pin
ectoplasm7-Nov-04 20:54
ectoplasm7-Nov-04 20:54 
GeneralI've finished random selection Pin
ectoplasm7-Nov-04 20:52
ectoplasm7-Nov-04 20:52 
GeneralUninitialized CRects can cause problems in selection in some cases Pin
eneam21-Oct-04 22:48
eneam21-Oct-04 22:48 
QuestionHow to Set Specialday? Pin
kijoonlee22-Jul-04 21:48
kijoonlee22-Jul-04 21:48 
AnswerRe: How to Set Specialday? Pin
Lehoanq13-Apr-06 23:32
Lehoanq13-Apr-06 23:32 
GeneralBugs, partially fixed Pin
Yogurt8-May-04 11:18
Yogurt8-May-04 11:18 
GeneralRe: Bugs, partially fixed #2 Pin
Yogurt14-May-04 10:39
Yogurt14-May-04 10:39 
GeneralRe: Bugs, partially fixed #2 Pin
John E1-Jun-04 2:09
John E1-Jun-04 2:09 
GeneralLocalization, act II - with fixes Pin
Yogurt8-May-04 10:49
Yogurt8-May-04 10:49 
GeneralRe: Localization, act II - with fixes Pin
John E7-Jun-04 3:59
John E7-Jun-04 3:59 
GeneralInternationalization Pin
John E26-Feb-04 5:43
John E26-Feb-04 5:43 
GeneralRe: Internationalization Pin
John E26-Feb-04 23:09
John E26-Feb-04 23:09 
GeneralRe: Internationalization Pin
Matt Gullett9-Mar-04 15:20
Matt Gullett9-Mar-04 15:20 

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

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