Win32 Controls - Month Calendar |
|
|
Practical Learning: Creating the Application |
|
Month Calendar Creation |
The Month Calendar control is part of the family of Common Controls defined in the comctl32.dll library. Therefore, before including it in your application, you must register it by calling the InitCommonControlsEx() function and assign the ICC_DATE_CLASSES value to the INITCOMMONCONTROLSEX::dwICC member variable. As always, there are two main ways you can create a control. You can use a resource script. If you use a script, the formula to follow is: The easiest way to create a combo box is through a resource script. The syntax used to create the control in a script is: CONTROL string, id,"SysMonthCal32", style, x, y, width, height You must start with the CONTROL class to indicate that you are going to create a control from the Comctl32.dll family of controls. The string factor can be anything. It is for controls that would need it. The Month Calendar control doesn't need it. Therefore, you can pass it as an empty string "" or provide any string you want. The id is the number used to identify the control in a resource header file. To indicate that you are creating a Month Calendar control, pass the class name as SysMonthCal32. The style and the extended-style factors are used to configure and prepare the behavior of the combo box. The x measure is its horizontal location with regards to the control's origin, which is located in the top left corner of the window that is hosting the combo box The y factor is the distance from control's origin, which is located in the top left corner of the window that is hosting the combo box, to the top-left side of the combo box The width and the height specify the dimensions of the control Instead of using a script, to create a Month Calendar control, you can use the CreateWindowEx() function and pass the name of the class as MONTHCAL_CLASS. |
Practical Learning: Creating the Control in a Script |
#define IDD_CONTROLSDLG 101 #define IDC_MONTHCALENDAR 102 |
#include "resource.h" IDD_CONTROLSDLG DIALOG 260, 200, 200, 120 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Windows Controls" FONT 8, "MS Shell Dlg" BEGIN CONTROL "",IDC_MONTHCALENDAR,"SysMonthCal32", WS_CHILD | WS_TABSTOP,10,10,118,96 DEFPUSHBUTTON "Close", IDCANCEL, 140,10,50,14 END |
#include <windows.h> #include <commctrl.h> #ifdef __BORLANDC__ #pragma argsused #endif #include "resource.h" //--------------------------------------------------------------------------- HWND hWnd; LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); //--------------------------------------------------------------------------- int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_CONTROLSDLG), hWnd, reinterpret_cast<DLGPROC>(DlgProc)); INITCOMMONCONTROLSEX InitCtrlEx; InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); InitCtrlEx.dwICC = ICC_PROGRESS_CLASS; InitCommonControlsEx(&InitCtrlEx); return 0; } //--------------------------------------------------------------------------- LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hWndDlg, 0); return TRUE; } break; } return FALSE; } //--------------------------------------------------------------------------- |
The Properties of a Month Calendar Control |
The Effects of the Control Dimensions |
After creating a Month Calendar control, it displays the current month and maybe only one month. To display more than one month, set the width of the control to provide enough space. Here is an example: #include "resource.h" IDD_CONTROLSDLG DIALOG 260, 200, 320, 120 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Windows Controls" FONT 8, "MS Shell Dlg" BEGIN CONTROL "",IDC_MONTHCALENDAR,"SysMonthCal32", WS_CHILD | WS_TABSTOP,10,10,240,96 DEFPUSHBUTTON "Close", IDCANCEL, 260,10,50,14 END
In the same way, you can increase the height to display many months. |
Colors: The Background of the Title Bar |
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 MonthCal_SetColor() function. Its syntax is: COLORREF MonthCal_SetColor(HWND hwndMC, INT iColor, COLORREF clr); The first argument is a handle to the Month Calendar control whose color you want to set or change. |
By default, the title of the Month Calendar control appears on top of a blue background. If you want a different color, pass the iColor argument as MCSC_TITLEBK, and pass the color of your choice as the clr argument. |
Here is an example:
//--------------------------------------------------------------------------- LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hWndMonthCal; hWndMonthCal = GetDlgItem(hWndDlg, IDC_MONTHCALENDAR); switch(Msg) { case WM_INITDIALOG: MonthCal_SetColor(hWndMonthCal, MCSC_TITLEBK, RGB(205, 50, 5)); return TRUE; case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hWndDlg, 0); return TRUE; } break; } return FALSE; } //---------------------------------------------------------------------------
Alternatively, you can send the MCM_SETCOLOR message. The syntax to use would be: lResult = SendMessage(HWND hWnd, MCM_SETCOLOR, WPARAM wParam, LPARAM lParam); In this case, pass the wParam argument as MCSC_TITLEBK, and pass the color of your choice as the lParam argument. |
Practical Learning: Changing the Background of the Title Bar |
//--------------------------------------------------------------------------- LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hWndMonthCal; hWndMonthCal = GetDlgItem(hWndDlg, IDC_MONTHCALENDAR); switch(Msg) { case WM_INITDIALOG: SendMessage(hWndMonthCal, MCM_SETCOLOR, MCSC_TITLEBK, RGB(205, 50, 5)); return TRUE; case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hWndDlg, 0); return TRUE; } break; } return FALSE; } //--------------------------------------------------------------------------- |
Colors: The Caption of the Title Bar |
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
call the MonthCal_SetColor() macro. Alternatively, you can send the MCM_SETCOLOR
message, pass the
wParam argument as MCSC_TITLETEXT, and pass the color of your choice as the
lParam argument.
The names of weekdays use the same color as the color set when passing the MCSC_TITLETEXT value as the wParam or the iColor argument. 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. |
Practical Learning: Changing the Color of the Title Bar Caption |
//--------------------------------------------------------------------------- LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hWndMonthCal; hWndMonthCal = GetDlgItem(hWndDlg, IDC_MONTHCALENDAR); switch(Msg) { case WM_INITDIALOG: SendMessage(hWndMonthCal, MCM_SETCOLOR, MCSC_TITLEBK, RGB(205, 50, 5)); MonthCal_SetColor(hWndMonthCal, MCSC_TITLETEXT, RGB(255, 250, 5)); return TRUE; case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hWndDlg, 0); return TRUE; } break; } return FALSE; } //---------------------------------------------------------------------------
Colors: The Caption of the Title Bar |
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, you can call the MonthCal_SetColor() macro or send a MCSC_TEXT message. Pass the iColor or the wParam as MCSC_TEXT and pass the color of your choice as the lParam or the Clr argument. |
Practical Learning: Changing the Color of the Current Month Days |
//--------------------------------------------------------------------------- LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hWndMonthCal; hWndMonthCal = GetDlgItem(hWndDlg, IDC_MONTHCALENDAR); switch(Msg) { case WM_INITDIALOG: SendMessage(hWndMonthCal, MCM_SETCOLOR, MCSC_TITLEBK, RGB(205, 50, 5)); MonthCal_SetColor(hWndMonthCal, MCSC_TITLETEXT, RGB(255, 250, 5)); MonthCal_SetColor(hWndMonthCal, MCSC_TEXT, RGB(128, 0, 5)); return TRUE; case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hWndDlg, 0); return TRUE; } break; } return FALSE; } //--------------------------------------------------------------------------- |
Colors: 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 the color of the days of the other months, you can call the MonthCal_SetColor() macro, pass the iColor argument as MCSC_TRAILINGTEXT, and pass the color of your choice as the clr argument. Alternatively, you can send the MCM_SETCOLOR message |
Colors: The Body Background |
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, you can call the MonthCal_SetColor() macro or send a MCM_SETCOLOR message, pass the iColor or the wParam argument as MCSC_MONTHBK, and pass the color of your choice as the Clr or the lParam argument. |
Today's Effect |
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: To programmatically hide the today label, you can apply the MCS_NOTODAY style. Here is an example: |
#include <commctrl.h> #include "resource.h" IDD_CONTROLSDLG DIALOG 260, 200, 200, 120 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Windows Controls" FONT 8, "MS Shell Dlg" BEGIN CONTROL "",IDC_MONTHCALENDAR,"SysMonthCal32", WS_CHILD | WS_TABSTOP | MCS_NOTODAY | MCS_NOTODAY,10,10,118,96 DEFPUSHBUTTON "Close", IDCANCEL, 140,10,50,14 END
We also mentioned that today date appears with a circle. If you want to hide just the circle, apply the MCS_NOTODAYCIRCLE style: |
#include <commctrl.h> #include "resource.h" IDD_CONTROLSDLG DIALOG 260, 200, 200, 120 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Windows Controls" FONT 8, "MS Shell Dlg" BEGIN CONTROL "",IDC_MONTHCALENDAR,"SysMonthCal32", WS_CHILD | WS_TABSTOP | MCS_NOTODAY | MCS_NOTODAY | MCS_NOTODAYCIRCLE,10,10,118,96 DEFPUSHBUTTON "Close", IDCANCEL, 140,10,50,14 END
As you may know already, to programmatically change the style of a control, for example to show or hide the today label, you can call the SetWindowLong() function. |
The First Day of the Week |
Under the title bar, the short names of week days display, using the format set in Control Panel. In US English, the first day is Sunday. If you want to start with a different day, you can call the MonthCal_SetFirstDayOfWeek() macro. Its syntax is: DWORD MonthCal_SetFirstDayOfWeek(HWND hwndMC, INT iDay); Alternatively, you can send the MCM_SETFIRSTDAYOFWEEK message using the following syntax: lResult = SendMessage(HWND hWndControl, MCM_SETFIRSTDAYOFWEEK, WPARAM wParam, LPARAM lParam); The first argument is the handle to the Month Calendar control whose first day you want to set. The wParam argument is not used and can be passed as 0. The iDay or the lParam argument is a constant integer of the following values:
DWORD MonthCal_GetFirstDayOfWeek(HWND hWndMC); To get the same information, you can send an MCM_GETFIRSTDAYOFWEEK message. Neither the wParam nor the lParam argument is used. Therefore, they must be passed as 0. Both the MonthCal_GetFirstDayOfWeek() macro and the SendMessage() function that carries the MCM_GETFIRSTDAYOFWEEK message returns a value of the above table. |
The Selected Day |
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. You also can programmatically select a day. To do this, you can call the MonthCal_SetCurSel() macro whose syntax is: BOOL MonthCal_SetCurSel(HWND hwndMC, LPSYSTEMTIME lpSysTime); Alternatively, you can send a MCM_SETCURSEL message. The syntax used is: lResult = SendMessage(HWND hWndControl, MCM_SETCURSEL, WPARAM wParam, LPARAM lParam); The wParam argument of the SendMessage() function is not used and can be passed as 0. The lpSysTime and the lParam arguments are passed as pointers to the Win32's SYSTEMTIME structure and therefore carry the returning value of the function. After a day has been selected, whether by you or the user, to find out what day was selected, you can call the MonthCal_GetCurSel() macro whose syntax is: BOOL MonthCal_GetCurSel(HWND hwndMC, LPSYSTEMTIME lpSysTime); To get the same information, you can send a MCM_GETCURSEL message using the following syntax: lResult = SendMessage(HWND hWndControl, MCM_GETCURSEL, WPARAM wParam, LPARAM lParam);
|
The Multiple Day Selection Option |
When the user clicks the Month Calendar control, one date is selected. To control whether the user can select one or more dates, you can apply the MCS_MULTISELECT style: |
#include <commctrl.h> #include "resource.h" IDD_CONTROLSDLG DIALOG 260, 200, 200, 120 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Windows Controls" FONT 8, "MS Shell Dlg" BEGIN CONTROL "",IDC_MONTHCALENDAR,"SysMonthCal32", WS_CHILD | WS_TABSTOP | MCS_NOTODAY | MCS_NOTODAY | MCS_NOTODAYCIRCLE | MCS_MULTISELECT, 10,10,118,96 DEFPUSHBUTTON "Close", IDCANCEL, 140,10,50,14 END
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 MonthCal_SetSelRange() macro whose syntax is: BOOL MonthCal_SetSelRange(HWND hwndMC, LPSYSTEMTIME lprgSysTimeArray); To perform the same operation, you can send a MCM_SETSELRANGE message using the following syntax: lResult = SendMessage(HWND hWndControl, MCM_SETSELRANGE, WPARAM wParam, LPARAM lParam); After the user has selected a range date on the calendar, to find out what that range is, you can call the
MonthCal_GetSelRange() macro. |
|
|