Home

Windows Controls: The Month Calendar

   

Introduction to the Month Calendar

 

Description

Microsoft Windows provides a control used to select dates on a colorful calendar:

The Month Calendar control

The dates used and the way they display are based on the Regional Settings of the Control Panel. It may also depend on the operating system. This convenient control is called a month calendar or simply a calendar. The title bar of the control displays two buttons and one label. The left button allows the user to select the previous value depending on the type that is displaying on the label (month, year, decade, or century). The user does this by clicking the left button. By default, the label displays the currently selected month and the year. The right button is used to get to the next value (month, year, decade, or century, depending on the value on the label).

Under the title bar, the short names of week days display, using the format set in the Windows Control Panel. In US English, the first day is usually Sun for Sunday. The first day can be changed by the programmer. On the control, the currently selected date is highlighted. In the main area, the numeric days of the month display on a white background (this color and any color on the control can be changed). To select a date, the user can click it in the list.

By default, the calendar opens with today's day highlighted. Using the buttons of the title bar, the month-year label, the user can change the date. If at one time the month calendar is displaying a date other than today, and if the user wants to return to today's date, he or she can:

  • Click the bottom label that displays Today (you as the programmer can hide the Today label if you want)
  • Right-click anywhere on the control and click Go To Today
The Month Calendar control allowing the user to select a year

If the month calendar displays regularly (with a month, a year, the week days, and the days of a month), if the user clicks the label that is between the buttons, the month calendar displays a list of 12 months from January to December, and the month of the date that was previously selected is highlighted. Here is an example:

The Month Calendar control allowing the user to select a year

If the month calendar is displaying a list of months:

  • To select a month, the user can click it
  • To get the 12 months of the previous year, the user can click the left button
  • To get the 12 months of the next year, the user can click the right button

If the month calendar is displaying the names of months and if the user clicks the year, the label would display a decade of the current year and the 9th year from it. The body of the month calendar would display the years in that decade, plus the year prior to that decade and the year after that decade:

The Month Calendar control allowing the user to select a year

That display has new options:

  • To select a year, the user can click it
  • To get a list of the previous 12 years, the user can click the left button
  • To get a list of the next 12 years, the user can click the right button

If the month calendar is displaying the numbers of 12 years and if the user clicks the label, the label would display a century from the current year and the 99th year from it. The body of the month calendar would display 12 labels that each shows a decade:

The Month Calendar control allowing the user to select a year

This time:

  • To select a decade, the user can click it
  • To get a list of the previous decades, the user can click the left button
  • To get a list of the next decades, the user can click the right button

The calendar can be configured to display more than one month. You have many options. You can display the months horizontally:

The Month Calendar control displaying two months

Or you can display them vertically:

The Month Calendar control displaying two months

If the control is displaying more than one month, the buttons would increment or decrement by the previous or next value (month, year, decade, or century) in the list. For example, if the control is displaying April and May and if the user clicks the left button, the control would display March and April. If the control is displaying April and May and if the user clicks the right button, the control would display May and June.

Practical LearningPractical Learning: Introducing the Month Calendar

  1. To create a new application, on the main menu, click File -> New Project...
  2. In the middle list, click MFC Application and set the name to TimeSheet1
  3. Click OK
  4. In the first page of the wizard, click Next
  5. In the second page of the wizard, click Dialog based and click Next
  6. In the third page of the wizard, click Finish
  7. On the dialog box, click the TODO label and press Delete

Creating a Month Calendar

To create a calendar, on the Toolbox, you can click the Month Calendar Control button Month Calendar Control and the desired container. The month calendar control is based on the CMonthCalCtrl class. Therefore, to dynamically create this control, declare a CMonthCalCtrl variable or a pointer to CMonthCalCtrl. Here is an example:

// Exercise1Dlg.h : header file
 
class CExercise1Dlg : public CDialog
{
// Construction
public:
	CExercise1Dlg(CWnd* pParent = NULL); // standard constructor
 
private:
	CMonthCalCtrl *ctlCalendar;
 
};

The CMonthCalCtrl class, like all other control-oriented classes of the MFC library, is equipped with a Create() member function that can be used to programmatically create a calendar and place it on a container. Here is an example:

CExercise1Dlg::CExercise1Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CExercise1Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CExercise1Dlg)
	
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 
	ctlCalendar = new CMonthCalCtrl;
}
 
	. . . No Change
 
/////////////////////////////////////////////////////////////////////////////
// CExercise1Dlg message handlers
 
BOOL CExercise1Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();
 
	// Set the icon for this dialog. The framework does this automatically
	// when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE); // Set big icon
	SetIcon(m_hIcon, FALSE); // Set small icon
 
	// TODO: Add extra initialization here
 
	ctlCalendar->Create(WS_TABSTOP | WS_CHILD | 
			WS_VISIBLE | WS_BORDER,
			CPoint(20, 20), this, 0x224);
 
	return TRUE; // return TRUE unless you set the focus to a control
}

Practical LearningPractical Learning: Introducing Check Boxes

  1. Design the dialog box as follows:
     
    Time Sheet
    Control Caption ID Align Left Other Properties
    Group Box Group Box Employee Identification      
    Static Text Static Text Employee #:      
    MFC MaskedEdit Control Edit Control   IDC_EMPLOYEE_NUMBER    
    Edit Control Edit Control   IDC_EMPLOYEE_NAME    
    Group Box Group Box Time Frame      
    Month Calendar Control Month Calendar Control   IDC_TIME_FRAME    
    Group Box Group Box Dates Worked - Time Value Worked      
    Static Text Static Text Monday      
    Static Text Static Text Tuesday      
    Static Text Static Text Wednesday      
    Static Text Static Text Thursday      
    Static Text Static Text Friday      
    Static Text Static Text Saturday      
    Static Text Static Text Sunday      
    Picture Control Picture Control       Type: Rectangle
    Static Text Static Text Monday IDC_MONDAY1    
    Static Text Static Text Tuesday IDC_TUESDAY1    
    Static Text Static Text Wednesday IDC_WEDNESDAY1    
    Static Text Static Text Thursday IDC_THURSDAY1    
    Static Text Static Text Friday IDC_FRIDAY1    
    Static Text Static Text Saturday IDC_SATURDAY1    
    Static Text Static Text Sunday IDC_SUNDAY1    
    Static Text Static Text Week 1:      
    Edit Control Edit Control   IDC_WEEK1MONDAY Right  
    Edit Control Edit Control   IDC_WEEK1TUESDAY Right  
    Edit Control Edit Control   IDC_WEEK1WEDNESDAY Right  
    Edit Control Edit Control   IDC_WEEK1THURSDAY Right  
    Edit Control Edit Control   IDC_WEEK1FRIDAY Right  
    Edit Control Edit Control   IDC_WEEK1SATURDAY Right  
    Edit Control Edit Control   IDC_WEEK1SUNDAY Right  
    Static Text Static Text Monday IDC_MONDAY2    
    Static Text Static Text Tuesday IDC_TUESDAY2    
    Static Text Static Text Wednesday IDC_WEDNESDAY2    
    Static Text Static Text Thursday IDC_THURSDAY2    
    Static Text Static Text Friday IDC_FRIDAY2    
    Static Text Static Text Saturday IDC_SATURDAY2    
    Static Text Static Text Sunday IDC_SUNDAY2    
    Static Text Static Text Week 2:      
    Edit Control Edit Control   IDC_WEEK2MONDAY Right  
    Edit Control Edit Control   IDC_WEEK2TUESDAY Right  
    Edit Control Edit Control   IDC_WEEK2WEDNESDAY Right  
    Edit Control Edit Control   IDC_WEEK2THURSDAY Right  
    Edit Control Edit Control   IDC_WEEK2FRIDAY Right  
    Edit Control Edit Control   IDC_WEEK2SATURDAY Right  
    Edit Control Edit Control   IDC_WEEK2SUNDAY Right  
  2. Right-click each of the edit controls and click Add Variable... Then create the variables as follows:
     
    ID
    Category Type Name
    IDC_EMPLOYEE_NUMBER Value CString m_EmployeeNumber
    IDC_EMPLOYEE_NAME Value CString m_EmployeeName
    IDC_TIME_FRAME Control CMonthCalCtrl m_TimeFrame
    IDC_MONDAY1 Value CString m_Monday1
    IDC_TUESDAY1 Value CString m_Tuesday1
    IDC_WEDNESDAY1 Value CString m_Wednesday1
    IDC_THURSDAY1 Value CString m_Thursday1
    IDC_FRIDAY1 Value CString m_Friday1
    IDC_SATURDAY1 Value CString m_Saturday1
    IDC_SUNDAY1 Value CString m_Sunday1
    IDC_WEEK1MONDAY Value double m_Week1Monday
    IDC_WEEK1TUESDAY Value double m_Week1Tuesday
    IDC_WEEK1WEDNESDAY Value double m_Week1Wednesday
    IDC_WEEK1THURSDAY Value double m_Week1Thursday
    IDC_WEEK1FRIDAY Value double m_Week1Friday
    IDC_WEEK1SATURDAY Value double m_Week1Saturday
    IDC_WEEK1SUNDAY Value double m_Week1Sunday
    IDC_MONDAY2 Value CString m_Monday2
    IDC_TUESDAY2 Value CString m_Tuesday2
    IDC_WEDNESDAY2 Value CString m_Wednesday2
    IDC_THURSDAY2 Value CString m_Thursday2
    IDC_FRIDAY2 Value CString m_Friday2
    IDC_SATURDAY2 Value CString m_Saturday2
    IDC_SUNDAY1 Value CString m_Sunday2
    IDC_WEEK2MONDAY Value double m_Week2Monday
    IDC_WEEK2TUESDAY Value double m_Week2Tuesday
    IDC_WEEK2WEDNESDAY Value double m_Week2Wednesday
    IDC_WEEK2THURSDAY Value double m_Week2Thursday
    IDC_WEEK2FRIDAY Value double m_Week2Friday
    IDC_WEEK2SATURDAY Value double m_Week2Saturday
    IDC_WEEK2SUNDAY Value double m_Week2Sunday
 

 

 
 
 
 

Using a Month Calendar

 

Introduction

A month calendar is primarily a Windows control. It gets its primary properties from the CMonthCalCtrl class. Based on this, when creating it, you can specify its location, its size, and other characteristics.

When the user clicks the calendar control, one date is selected. As mentioned in our description, you can give the control the ability to display more than one month. To make this possible, when visually creating the control, set its width to have enough space. In the same way, you can increase the height to display many months. This allows you to display as many months as you judge necessary. Here is an example:

Month Calendar

Practical LearningPractical Learning: Enlarging a Month Calendar

  • Enlarge the month calendar control as follows:

Time Sheet

The Current Selection of the Month Calendar

At any time, a particular date is selected and has an ellipse with the same color as the background of the title bar. By default, the selected date is today's date. When the user clicks the calendar, a date is selected. To find out what date the user selected, you can access the CMonthCalCtrl::GetCurSel() member function. It is overloaded in three versions whose syntaxes are:

BOOL GetCurSel(COleDateTime& refDateTime) const;
BOOL GetCurSel(CTime& refDateTime) const;
BOOL GetCurSel(LPSYSTEMTIME pDateTime) const;

Here is an example:

void CExercise1Dlg::OnRetrieveBtn() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
	CTime tme = this->m_dtpCurrent.GetCurrentTime();
	this->m_Result.Format("%s", tme.Format("%A, %B %d, %Y"));
	UpdateData(FALSE);
}

When the date of a month calendar has been changed, the control sends an MCN_SELCHANGE message. The event of this message is applied through a structure named NMSELCHANGE:

typedef struct tagNMSELCHANGE {
  NMHDR      nmhdr;
  SYSTEMTIME stSelStart;
  SYSTEMTIME stSelEnd;
} NMSELCHANGE, *LPNMSELCHANGE;

Practical LearningPractical Learning: Selecting a Date

  1. On the dialog box, click the month calendar
  2. In the Properties window, click the Control Events button Control Events
  3. Click MCN_SELCHANGE, then click its arrow and select <Add> OnMcnSellchangeTimeFrame
  4. Implement the event as follows:
    void CTimeSheet1Dlg::OnMcnSelchangeTimeFrame(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMSELCHANGE pSelChange = reinterpret_cast<LPNMSELCHANGE>(pNMHDR);
        // TODO: Add your control notification handler code here
        UpdateData();
    
        if( pSelChange->stSelStart.wDayOfWeek != 1 )
        {
    	MessageBox(L"The first day of your time frame must be a Monday",
                       L"Bethesda Car Rental", 33);
    	return;
        }
    
        UpdateData(FALSE);
    
        *pResult = 0;
    }
  5. Execute the application and try selecting a range of dates
  6. Close the form and return to your programming environment

Selecting Multiple Dates

When the user clicks the month calendar control, one date is selected. To control whether the user can select one or more dates, at design time, set the value of the Multi Select property accordingly. For example, if you want the user to select a range of dates on the control, set the Muilti Select property to true. The month calendar may appear as follows:

Month Calendar

To programmatically allow the user to select more than one day, apply the MCS_MULTISELECT style:

BOOL CExercise1Dlg::OnInitDialog()
{	CDialog::OnInitDialog();
 
	// Set the icon for this dialog. The framework does this automatically
	// when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE); // Set big icon
	SetIcon(m_hIcon, FALSE); // Set small icon
 
	// TODO: Add extra initialization here
 
	ctlCalendar->Create(WS_TABSTOP | WS_CHILD | 
		WS_VISIBLE | WS_BORDER |
		MCS_NOTODAYCIRCLE | MCS_MULTISELECT,
	CPoint(20, 20), this, 0x224);
 
	return TRUE; // return TRUE unless you set the focus to a control
}

With this property set, the user can select many days in the calendar. You also can programmatically select a range of days. To to this, you can call the CMonthCalCtrl::SetSelRange() member function. It comes in three versions whose syntaxes are:

BOOL SetSelRange(const COleDateTime& pMinRange, const COleDateTime& pMaxRange);
BOOL SetSelRange(const CTime& pMinRange, const CTime& pMaxRange);
BOOL SetSelRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange);

After the user has selected a range date on the calendar, to find out what that range is, you can call the CMonthCalCtrl::GetSelRange() member function.

As mentioned already, to change the month and subsequently the year of the calendar, the user can click the buttons continuously. To control the allowable dates the user can navigate from and to, you can call the CMonthCalCtrl::SetRange() member function. It comes in three versions whose syntaxes are:

BOOL SetRange(const COleDateTime* pMinRange, const COleDateTime* pMaxRange);
BOOL SetRange(const CTime* pMinRange, const CTime* pMaxRange);
BOOL SetRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange);

The first argument, nMinRange is the starting date of the desired range. The second argument, nMaxRange, is the end desired date the user can navigate to.

The First Day of the Week

Under the title bar, the short names of week days display, using the format set in the Control Panel. In US English, the first day of the week is Sunday. If you want to start with a different day, call the SetFirstDayOfWeek() member function. Its syntax is:

BOOL SetFirstDayOfWeek(int iDay, int* lpnOld = NULL);

The first argument, and the only one required, must be an integer of the following values:

Value Weekday
0 Monday
1 Tuesday
2 Wednesday
3 Thursday
4 Friday
5 Saturday
6 SSunday

If the calendar is already functioning, to find what its first day of the week is, you can call the GetFirstDayOfWeek() member function. Its syntax is:

iint GetFirstDayOfWeek(BOOL* pbLocal = NULL) const;

This member function returns an integer that is one of the values in the above table.

Showing Today

The month calendar control is used to let the user know today's date in two ways. On the calendar, today's date is circled by a hand-drawn ellipse. In the bottom section of the calendar, today's date is also displayed as a sentence. At design time, to display or hide the indication of today's date, use the No Today property. If it is checked or set to True, which is the default in MFC, a circled label would not appear at the bottom of the control.

If it is unchecked or set to False, a circled label would not appear at the bottom of the control as seen in the previous screenshots.

As mentioned already, by default, the today label at the bottom of the control appears. To programmatically hide the today label, you can apply the MCS_NOTODAY style. Here is an example:

BOOL CExercise1Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();
 
	// Set the icon for this dialog. The framework does this automatically
	// when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE); // Set big icon
	SetIcon(m_hIcon, FALSE); // Set small icon
 
	// TODO: Add extra initialization here
 
	ctlCalendar->Create(WS_TABSTOP | WS_CHILD | 
		WS_VISIBLE | WS_BORDER | MCS_NOTODAY,
		CPoint(20, 20), this, 0x224);
 
	return TRUE; // return TRUE unless you set the focus to a control
}

We also mentioned that today date appears with a circle. If you want to hide just the circle, apply the MCS_NOTODAYCIRCLE style:

BOOL CExercise1Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();
 
	// Set the icon for this dialog. The framework does this automatically
	// when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE); // Set big icon
	SetIcon(m_hIcon, FALSE); // Set small icon
 
	// TODO: Add extra initialization here
	ctlCalendar->Create(WS_TABSTOP | WS_CHILD | 
		WS_VISIBLE | WS_BORDER |
		MCS_NOTODAYCIRCLE,
		CPoint(20, 20), this, 0x224);
 
	return TRUE; // return TRUE unless you set the focus to a control
}

Calendar

The Colors of a Month Calendar

 

Introduction to Setting the Colors of a Month Calendar

To make it a highly visual object, a calendar uses different colors to represent the background, week days, the background of the title bar, the text of the title bar, the text of the days of the previous month, and the text of the days of the subsequent month. Of course, you can programmatically change these colors. Although any color is allowed in any category, you should make sure that the calendar is still reasonably appealing and usable.

To change the colors of the month calendar control, you can call the CMonthCalCtrl::SetColor() member function. Its syntax is:

COLORREF SetColor(int nRegion, COLORREF ref);

The Background Color of the Title Bar

By default, the title of the month calendar control appears on top of a blue background. If you want a different color, pass the nRegion argument as MCSC_TITLEBK, and pass the color of your choice as the ref argument. Here is an example:

Month Calendar

public:
	CMonthCalCtrl m_MonthCalendar;
	afx_msg void OnBnClickedMonthCal();
};

----------------------------

. . . No Change

void CExerciseDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_MONTH_CALENDAR, m_MonthCalendar);
}

BEGIN_MESSAGE_MAP(CExerciseDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_MONTH_CAL, &CExerciseDlg::OnBnClickedMonthCal)
END_MESSAGE_MAP()

// CExerciseDlg message handlers

. . . No Change

void CExerciseDlg::OnBnClickedMonthCal()
{
	// TODO: Add your control notification handler code here
	m_MonthCalendar.SetColor(MCSC_TITLEBK, RGB(205, 50, 0));
}

Month Calendar

The Text Color of the Title

By default, the labels on the title bar display in a white color. To change the color used to paint the text of the labels, you can pass the nRegion argument as MCSC_TITLETEXT, and pass the color of your choice as the ref argument. Here is an example:

void CExerciseDlg::OnBnClickedMonthCal()
{
	// TODO: Add your control notification handler code here
	m_MonthCalendar.SetColor(MCSC_TITLEBK, RGB(205, 50, 0));
	m_MonthCalendar.SetColor(MCSC_TITLETEXT, RGB(255, 255, 45));
}
Month Calendar

The Numeric Day Background Color

The names of weekdays use the same color as the color set when passing the MCSC_TITLETEXT value as the nRegion argument to the SetColor() member function.

Under the names of the week, there is a horizontal line used as the separator. By default, this line separator is painted in black but it uses the same color as the numeric values of the days of the selected month.

Under the line separator, the numeric days of the month are listed. By default, the numeric days of the control display above a white background which is the Window system color. To change the background color of the area where the numeric days appear, pass the nRegion of the SetColor() member function as MCSC_MONTHBK, and pass the color of your choice as the ref argument. Here is an example:

void CExerciseDlg::OnBnClickedMonthCal()
{
	// TODO: Add your control notification handler code here
	m_MonthCalendar.SetColor(MCSC_TITLEBK, RGB(205, 50, 0));
	m_MonthCalendar.SetColor(MCSC_TITLETEXT, RGB(255, 255, 45));
	m_MonthCalendar.SetColor(MCSC_MONTHBK, RGB(245, 225, 220));
}

Month Calendar

The Font Color of the Days of the Trailing Months

The numbers of the days of the month display in two colors. The real days of the selected month display, by default, in a black color as the WindowText system color. To change this color, pass the nRegion of the SetColor() member function as MCSC_TRAILINGTEXT, and pass the color of your choice as the ref argument. Here is an example:

void CExerciseDlg::OnBnClickedMonthCal()
{
    // TODO: Add your control notification handler code here
    m_MonthCalendar.SetColor(MCSC_TITLEBK, RGB(205, 50, 0));
    m_MonthCalendar.SetColor(MCSC_TITLETEXT, RGB(255, 255, 45));
	
    m_MonthCalendar.SetColor(MCSC_TRAILINGTEXT, RGB(0, 205, 255));
}
Month Calendar

The Font Color of the Days of the Current Month

Under the names of the week and their line separator, the numeric days of the month are listed. These days display in a different color. To specify the color of the days of the current month, pass the nRegion of the SetColor() member function as MCSC_TEXT, and pass the color of your choice as the ref argument. Here is an example:

void CExerciseDlg::OnBnClickedMonthCal()
{
	// TODO: Add your control notification handler code here
	m_MonthCalendar.SetColor(MCSC_TITLEBK, RGB(205, 50, 0));
	m_MonthCalendar.SetColor(MCSC_TITLETEXT, RGB(255, 255, 45));
	m_MonthCalendar.SetColor(MCSC_TEXT, RGB(15, 5, 255));
	m_MonthCalendar.SetColor(MCSC_TRAILINGTEXT, RGB(0, 205, 255));
}
Month Calendar
 
 
   
 

Home Copyright © 2010-2011 FunctionX, Inc.