Contents Index Topic Contents | ||
Previous Topic: NMLVODSTATECHANGE Next Topic: Month Calendar Control Reference |
Month Calendar Controls
A month calendar control implements a calendar-like user interface. This provides the user with a very intuitive and recognizable method of entering or selecting a date. The control also provides the application with the means to obtain and set the date information in the control using existing data types.
Month Calendar Control Reference
About Month Calendar Controls
A month calendar control provides a simple and intuitive way for a user to select a date from a familiar interface. The following illustration shows a month calendar control in a dialog box.
An application creates a month calendar control by calling the CreateWindowEx function, specifying MONTHCAL_CLASS as the window class. The class is registered when the month calendar class is loaded from the common controls dynamic-link library (DLL). Register this class by calling the InitCommonControlsEx function, specifying the ICC_DATE_CLASSES bit flag in the accompanying INITCOMMONCONTROLSEX structure.
Note The month calendar control is implemented in version 4.70 and later of Comctl32.dll.
The Month Calendar Control User Interface
The month calendar control user interface allows the user to select a date from the displayed days or change the control's display in various ways.
- Scrolling the control's display.
By default, when a user clicks the arrow buttons in the top left or top right of the month calendar control, it updates its display to show the previous or next month. If the month calendar control is displaying more than one month at a time, the display changes by the number of months currently in view. That is, if the month calendar displays January, February, and March and the user clicks the top right arrow button, the control updates its display to show April, May, and June. The user can also perform the same action by clicking the partial months displayed before the first month and after the last month.
An application can change the number of months by which the control updates its display by using the MCM_SETMONTHDELTA message or the corresponding macro, MonthCal_SetMonthDelta.
- Selecting a nonadjacent month.
When a user clicks the name of a displayed month, a pop-up menu appears that lists all months within the year. The user can select a month on the list. If the user's selection is not visible, the month calendar control scrolls its display to show the chosen month.
- Selecting a different year.
If the user clicks the year displayed next to a month name, an up-down control appears in place of the year. The user can change the year with this control. The month calendar control updates its display for the selected year when the up-down control loses focus.
- Selecting the current day.
If a month calendar control is not using the MCS_NOTODAY style, the user can return to the current day by clicking the "today" text at the bottom of the control. If the current day is not visible, the control updates its display to show it.
Day States
Month calendar controls that use the MCS_DAYSTATE style support day states. The control uses day state information to determine how it draws specific days within the control. Day state information is expressed as a 32-bit data type, MONTHDAYSTATE. Each bit in a MONTHDAYSTATE bit field (1 through 31) represents the state of a day in a month. If a bit is on, the corresponding day will be displayed in bold; otherwise it will be displayed with no emphasis.
An application can explicitly set day state information by sending the MCM_SETDAYSTATE message or by using the corresponding macro, MonthCal_SetDayState. Additionally, month calendar controls that use the MCS_DAYSTATE style send MCN_GETDAYSTATE notification messages to request day state information. For more information on supporting day states, see Processing the MCN_GETDAYSTATE Notification Message and Preparing the MONTHDAYSTATE Array.
Month Calendar Control Styles
Month calendar controls have several styles that determine their appearance and behavior. When you create the control using CreateWindowEx, include the desired styles in the dwStyle parameter.
After creating the control, you can change all of the styles except for MCS_DAYSTATE and MCS_MULTISELECT. To change these styles, you will need to destroy the existing control and create a new one that has the desired styles. To retrieve or change any other window styles, use the GetWindowLong and SetWindowLong functions.
Month calendar controls that use the MCS_MULTISELECT style allow the user to select a range of days. By default, the control allows the user to select seven contiguous days. Your application can change the control's default behavior by using the MCM_SETMAXSELCOUNT message or the accompanying macro, MonthCal_SetMaxSelCount.
When a month calendar control uses the MCS_WEEKNUMBERS style, it displays week numbers at the left side of each month. If the MCS_NOTODAY style is applied, the control no longer circles the current day.
The MCS_DAYSTATE style is helpful when you want the control to highlight specific dates by displaying them in bold. For more information, see Day States.
Month Calendar Control Notification Messages
A month calendar control sends notification messages when it receives user input or must request day state information (MCS_DAYSTATE style only). The control's parent receives these notifications as WM_NOTIFY messages.
The following notification messages are used with month calendar controls.
Notification Description MCN_GETDAYSTATE Requests information about which days should be displayed in bold. For more information, see Preparing the MONTHDAYSTATE Array. MCN_SELCHANGE Notifies the parent that the selected date or range of dates has changed. The control sends this notification when the user explicitly changes the selection within the current month or when the selection is implicitly changed in response to next/previous month navigation. MCN_SELECT Notifies the parent that the user has explicitly selected a date. Times in the Month Calendar Control
Because the month calendar control cannot be used to select a time, the time related fields of the SYSTEMTIME structure need to be handled differently. When the control is created, it will insert the current time into its "today" date and time.
When a time is later set programmatically, the control will either copy the time fields as they are or validate them first and then, if invalid, store the current default times. Following is a list of the messages that set a date and a description of how the time fields are treated by the message.
MCM_SETCURSEL The control will copy the time fields as they are, without validation or modification. MCM_SETRANGE The time fields of the structures passed in will be validated. If they are valid, the time fields will be copied without modification. If they are invalid, the control will copy the time fields from the "today" date and time. MCM_SETSELRANGE The time fields of the structures passed in will be validated. If they are valid, the time fields will be copied without modification. If they are invalid, the control will retain the time fields from the current selection ranges. MCM_SETTODAY The control will copy the time fields as they are, without validation or modification. When a date is retrieved from the control, the time fields will be copied from the stored times without modification. Handling of the time fields by the control is provided as a convenience to the programmer. The control does not examine or modify the time fields as a result of any operation other than those listed above.
Using Month Calendar Controls
This section provides information and sample code for implementing month calendar controls.
Creating a Month Calendar Control
To create a month calendar control, use the CreateWindowEx function, specifying MONTHCAL_CLASS as the window class. You must first register the window class by calling the InitCommonControlsEx function, specifying the ICC_DATE_CLASSES bit in the accompanying INITCOMMONCONTROLSEX structure.
The following example demonstrates how to create a month calendar control in an existing modeless dialog box. Note that the size values passed to CreateWindowEx are all zeros. Because the minimum required size depends on the font the control uses, the DoNotify example function uses the MonthCal_GetMinReqRect macro to request size information and then resizes the control by calling SetWindowPos.
// CreateMonthCal -- Creates a month calendar control in a dialog box. // Returns the handle to the month calendar control // if successful, or NULL otherwise. // // hwndOwner -- Handle to the owner of the dialog box. // g_hinst -- Global handle to the program instance. // ///// HWND WINAPI CreateMonthCal(HWND hwndOwner) { HWND hwnd; RECT rc; INITCOMMONCONTROLSEX icex; // Load the window class. icex.dwSize = sizeof(icex); icex.dwICC = ICC_DATE_CLASSES; InitCommonControlsEx(&icex); // Create a modeless dialog box to hold the control. g_hwndDlg = CreateDialog(g_hinst, MAKEINTRESOURCE(IDD_DIALOG1), hwndOwner, DlgProc); // Create the month calendar. hwnd = CreateWindowEx(0, MONTHCAL_CLASS, "", WS_BORDER | WS_CHILD | WS_VISIBLE | MCS_DAYSTATE, 0,0,0,0, // resize it later g_hwndDlg, NULL, g_hinst, NULL); // Get the size required to show an entire month. MonthCal_GetMinReqRect(hwnd, &rc); // Arbitrary values #define LEFT 35 #define TOP 40 // Resize the control now that the size values have been obtained. SetWindowPos(hwnd, NULL, TOP, LEFT, LEFT + rc.right, TOP + rc.bottom, SWP_NOZORDER); // Set colors for aesthetics. MonthCal_SetColor(hwnd, MCSC_BACKGROUND, RGB(175,175,175)); MonthCal_SetColor(hwnd, MCSC_MONTHBK, RGB(248,245,225)); return(hwnd); }Processing the MCN_GETDAYSTATE Notification Message
Month calendar controls send the MCN_GETDAYSTATE notification message to request information about how the days within the visible months should be displayed. The following application-defined function, DoNotify, processes MCN_GETDAYSTATE by filling an array of MONTHDAYSTATE values to highlight the 15th day of each month.
DoNotify extracts the number of MONTHDAYSTATE values needed from the cDayState member of the NMDAYSTATE structure that lParam points to. It then loops to set the 15th bit in each element of the array, using the application-defined BOLDDAY macro.
BOOL WINAPI DoNotify(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { #define BOLDDAY(ds,iDay) if(iDay>0 && iDay<32)\ (ds)|=(0x00000001<<(iDay-1)) #define lpnmDS ((NMDAYSTATE *)lParam) #define MAX_MONTHS 12 MONTHDAYSTATE mds[MAX_MONTHS]; INT i, iMax; LPNMHDR hdr = (LPNMHDR)lParam; switch(hdr->code){ case MCN_GETDAYSTATE: iMax=lpnmDS->cDayState; for(i=0;i<iMax;i++){ mds[i] = (MONTHDAYSTATE)0; BOLDDAY(mds[i],15); } lpnmDS->prgDayState = mds; break; } return FALSE; }Preparing the MONTHDAYSTATE Array
Both the MCM_SETDAYSTATE message and MCN_GETDAYSTATE notification message require an array of MONTHDAYSTATE values to determine how dates will be displayed. Each month that the control displays must have a corresponding element within the array.
To support these messages, your application must properly prepare the array. The following is a simple macro that sets a bit in a MONTHDAYSTATE value for a given day within that month.
#define BOLDDAY(ds,iDay) if(iDay>0 && iDay<32)\ (ds)|=(0x00000001<<(iDay-1))Using this macro, an application could simply loop through an array of important dates, setting bits within the corresponding array elements. This approach is not the most efficient, of course, but works well for many purposes. As long as your application sets MONTHDAYSTATE bits appropriately, it does not matter how those bits were set.
Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.