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

MS Outlook style miniature calendar control

0.00/5 (No votes)
28 Jan 2002 1  
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.

(Standard 1 month view demonstrating Today and None buttons)

(12 month view)

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

(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 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