|
The calendar can be configured to display more than one month. Here is an example that displays two months:
If the control is displaying more than one month, the buttons would increment or decrement by the previous or next month 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 the user clicks the right button, the control would display May and June. Also, to select any month of the current year, the user can click the name of the month, which displays the list of months and
this allows the user to click the desired month:
To select a year, the user can click the year number. This changes the year label into a spin button:
To change the year, the user can click the up or down arrows of the spin button. As the spin button is displaying, the user can also use the arrow keys of the keyboard to increase or decrease the value.
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 usually Sunday. The first day can be changed by the programmer.
On the control, the currently selected date has a circle around. To select a date on the control, the user clicks the desired date, which changes from the previous selection.
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 as we will see in the next section). To select a date, the user clicks it in the list. By default, the calendar opens with today's day circled with a hand-drawn-look-alike ellipse. Using the buttons of the title bar, the month label, and/or the year, the user can change the date. If at one time the 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).
To create a calendar control, you can click the
MonthCalendar button
in the Toolbox and click the form or the desired container. The MonthCalendar
control is based on the MonthCalendar class, which is based on Control.
Therefore, to create a calendar control, declare a variable or type MonthCalendar
and initialize it appropriately.
|
Practical
Learning: Introducing the Month Calendar Control
|
|
- Start a new Windows Application named PayrollProcessing2
- In the Solution Explorer, right-click Form1.cs and click Rename
- Type PayrollProcessing.cs and press Enter
- Design the form as follows:
- On the form, double-click the Calculate button and implement its event as
follows:
private void btnCalculate_Click(object sender, EventArgs e)
{
double monday1 = 0.00, tuesday1 = 0.00, wednesday1 = 0.00,
thursday1 = 0.00, friday1 = 0.00, saturday1 = 0.00,
sunday1 = 0.00, monday2 = 0.00, tuesday2 = 0.00,
wednesday2 = 0.00, thursday2 = 0.00,
friday2 = 0.00, saturday2 = 0.00, sunday2 = 0.00;
double totalHoursWeek1, totalHoursWeek2;
double regHours1 = 0.00, regHours2 = 0.00,
ovtHours1 = 0.00, ovtHours2 = 0.00;
double regAmount1 = 0.00, regAmount2 = 0.00,
ovtAmount1 = 0.00, ovtAmount2 = 0.00;
double regularHours, overtimeHours;
double regularAmount, overtimeAmount, totalEarnings;
double hourlySalary = 0.00;
// Retrieve the hourly salary
try
{
hourlySalary = double.Parse(txtHourlySalary.Text);
}
catch (FormatException)
{
MessageBox.Show(
"The value you typed for the salary is invalid \n" +
"Please try again");
txtHourlySalary.Focus();
}
// Retrieve the value of each day worked
try
{
monday1 = double.Parse(txtMonday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtMonday1.Focus();
}
try
{
tuesday1 = double.Parse(txtTuesday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
this.txtTuesday1.Focus();
}
try
{
wednesday1 = double.Parse(txtWednesday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtWednesday1.Focus();
}
try
{
thursday1 = double.Parse(txtThursday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtThursday1.Focus();
}
try
{
friday1 = double.Parse(txtFriday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtFriday1.Focus();
}
try
{
saturday1 = double.Parse(txtSaturday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtSaturday1.Focus();
}
try
{
sunday1 = double.Parse(txtSunday1.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtSunday1.Focus();
}
try
{
monday2 = double.Parse(txtMonday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
this.txtMonday2.Focus();
}
try
{
tuesday2 = double.Parse(txtTuesday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
this.txtTuesday2.Focus();
}
try
{
wednesday2 = double.Parse(txtWednesday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
this.txtWednesday2.Focus();
}
try
{
thursday2 = double.Parse(txtThursday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtThursday2.Focus();
}
try
{
friday2 = double.Parse(txtFriday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtFriday2.Focus();
}
try
{
saturday2 = double.Parse(txtSaturday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtSaturday2.Focus();
}
try
{
sunday2 = double.Parse(txtSunday2.Text);
}
catch (FormatException)
{
MessageBox.Show("You typed an invalid value\n" +
"Please try again");
txtSunday2.Focus();
}
// Calculate the total number of hours for each week
totalHoursWeek1 = monday1 + tuesday1 + wednesday1 +
thursday1 + friday1 + saturday1 + sunday1;
totalHoursWeek2 = monday2 + tuesday2 + wednesday2 +
thursday2 + friday2 + saturday2 + sunday2;
// The overtime is paid time and half
double ovtSalary = hourlySalary * 1.5;
// If the employee worked under 40 hours, there is no overtime
if (totalHoursWeek1 < 40)
{
regHours1 = totalHoursWeek1;
regAmount1 = hourlySalary * regHours1;
ovtHours1 = 0.00;
ovtAmount1 = 0.00;
} // If the employee worked over 40 hours, calculate the overtime
else if (totalHoursWeek1 >= 40)
{
regHours1 = 40;
regAmount1 = hourlySalary * 40;
ovtHours1 = totalHoursWeek1 - 40;
ovtAmount1 = ovtHours1 * ovtSalary;
}
if (totalHoursWeek2 < 40)
{
regHours2 = totalHoursWeek2;
regAmount2 = hourlySalary * regHours2;
ovtHours2 = 0.00;
ovtAmount2 = 0.00;
}
else if (totalHoursWeek2 >= 40)
{
regHours2 = 40;
regAmount2 = hourlySalary * 40;
ovtHours2 = totalHoursWeek2 - 40;
ovtAmount2 = ovtHours2 * ovtSalary;
}
regularHours = regHours1 + regHours2;
overtimeHours = ovtHours1 + ovtHours2;
regularAmount = regAmount1 + regAmount2;
overtimeAmount = ovtAmount1 + ovtAmount2;
totalEarnings = regularAmount + overtimeAmount;
txtRegularTime.Text = regularHours.ToString("F");
txtOvertime.Text = overtimeHours.ToString("F");
txtRegularAmount.Text = regularAmount.ToString("F");
txtOvertimeAmount.Text = overtimeAmount.ToString("F");
txtNetPay.Text = totalEarnings.ToString("F");
}
|
- Save the form
|
Using a Month Calendar Control |
|
As mentioned in our description, the calendar control
displays the days of a selected month. The control also displays the remaining
days, if any, of the first week of the currently selected month; that is, the
days of the previous month that share the week with the first day of the first
week of the selected month. The control also displays the first days of the
subsequent month that share the week with the last day of the current month.
To use the calendar control, the user can click a date,
whether it a date from the current month or a day of the other (previous and
next) month. When the user has clicked a date to select it, the control fires a DateSelected
event. The DateSelected event is of type DateRangeEventArgs.
The user can also select a date using the keyboard. To do
this, the user must first give focus to the control. This is possible by
pressing Tab continuously until the control receives focus (or by clicking any
date on the control. To select a date using the keyboard, the user can
continually press one of the arrow keys (on the keyboard) until the desired date
is selected.
You too can programmatically select a date on the calendar
control. To do this, assign a valid DateTime value to both the SelectionStart
and the SelectionEnd properties. Here is an example:
private void btnSelect_Click(object sender, EventArgs e)
{
monthCalendar1.SelectionStart = new DateTime(1988, 12, 5);
monthCalendar1.SelectionEnd = new DateTime(1988, 12, 5);
}
When a date has been selected, whether by the user (using
the mouse or the keyboard) or by you (through code), the control fires a DateChanged
event. The DateChanged event is of type DateRangeEventArgs.
The DateRangeEventArgs class is equipped with two
properties: Start and End. When the user clicks a date, these two
properties hold the date that was clicked. This means that you can use either of
these properties to know the date that was clicked. Both the Start and
the End properties are of type DateTime.
|
Practical
Learning: Showing Two Months
|
|
- On the form, click the calendar control
- In the Properties window, click the Events button and double-click
DateSelected
- Implement the event as follows:
private void calTimeFrame_DateSelected(object sender,
DateRangeEventArgs e)
{
DateTime DateStart = e.Start;
if (DateStart.DayOfWeek != DayOfWeek.Monday)
MessageBox.Show("The first day of your time frame must be a Monday");
}
|
- Execute the application and try selecting a range of dates
- Close the form and return to your programming environment
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 creating the control, set its width to have enough
space. In the same way, you can increase the height to display many months.
To select
more than one date, the user can click one date, hold the mouse down, and drag to the left, the right,
up or down:
 The
user can also select a range of dates using the keyboard or using a combination
of the mouse and the keyboard. To do this, the user must first give focus to the
control. To select a range of dates using the keyboard, the user can press and
hold Shift, then press one of the arrow keys continually until the last date of
the desired range is selected (in reality, we will see that there is a
property that controls the maximum range of dates that can be selected). To
select a range of dates using a combination of the mouse and keyboard, the user
can click the first date, press and hold Shift, then click the last date.
After selecting the days, the starting date is stored in the
SelectionStart property. The last date of the selection is stored in the SelectionEnd
property. Both properties are of DateTime type. The range of the selected
dates is stored in a SelectionRange value. SelectionRange is simply a class that
can give you information about the beginning and the end of a selected range of
dates.
To programmatically select a date, assign the starting to
the SelectionStart property and assign the last date to the SelectionEnd
property.
By default, the user can select only up to 7 days at a time. If you want the
user to be able to select more or less days than that. Here is an example where
the user have selected dates from the 11 to the 20th, that is 10 days:
If you configure the control to display more than one month, the user can select
days from one month to another as long as the days are in a range. Here is an
example of a calendar that displays two months and the user had selected dates
from September 21st, 2007 to October 11th, 2007:
After selecting a range of dates, the control fires a DateChanged
event, which is of type DateRangeEventArgs. We saw earlier that the DateRangeEventArgs
class has two properties. The DateRangeEventArgs.Start property holds the
starting date of the range that the user made. The DateRangeEventArgs.End
holds the last date from the range that the user made.
|
Practical
Learning: Showing Two Months
|
|
- On the form, click the calendar control and drag its right border so it
can display two months:

- Right-click the form and click View Code
- Change the DateSelected event as follows:
void EnableForInvalidDate(bool Enable)
{
if (Enable == true)
{
txtMonday1.Enabled = true; txtMonday2.Enabled = true;
txtTuesday1.Enabled = true; txtTuesday2.Enabled = true;
txtWednesday1.Enabled = true; txtWednesday2.Enabled = true;
txtThursday1.Enabled = true; txtThursday2.Enabled = true;
txtFriday1.Enabled = true; txtFriday2.Enabled = true;
txtSaturday1.Enabled = true; txtSaturday2.Enabled = true;
txtSunday1.Enabled = true; txtSunday2.Enabled = true;
txtRegularTime.Enabled = true; txtRegularAmount.Enabled = true;
txtOvertime.Enabled = true; txtOvertimeAmount.Enabled = true;
txtNetPay.Enabled = true; btnCalculate.Enabled = true;
}
else if (Enable == false)
{
txtMonday1.Enabled = false; txtMonday2.Enabled = false;
txtTuesday1.Enabled = false; txtTuesday2.Enabled = false;
txtWednesday1.Enabled = false; txtWednesday2.Enabled = false;
txtThursday1.Enabled = false; txtThursday2.Enabled = false;
txtFriday1.Enabled = false; txtFriday2.Enabled = false;
txtSaturday1.Enabled = false; txtSaturday2.Enabled = false;
txtSunday1.Enabled = false; txtSunday2.Enabled = false;
txtRegularTime.Enabled = false; txtRegularAmount.Enabled = false;
txtOvertime.Enabled = false; txtOvertimeAmount.Enabled = false;
txtNetPay.Enabled = false; btnCalculate.Enabled = false;
}
}
private void calTimeFrame_DateSelected(object sender,
DateRangeEventArgs e)
{
DateTime DateStart = e.Start;
// Each payroll will cover 2 weeks
// This application assumes that the company started
// implementing the time sheet on January 1st, 2007
// Our week day will go from Monday of the first week
// to Sunday of the following week
// The first date of the time frame must be a Monday
if (DateStart.DayOfWeek != DayOfWeek.Monday)
{
MessageBox.Show("The first day of your time frame must be a Monday");
EnableForInvalidDate(false);
return;
}
else
EnableForInvalidDate(true);
// Now that the user has selected a date that starts on Monday,
// We will check that it corresponds to
// 2 weeks by 2 weeks after January 1st, 2007
// To start, we must get the difference of days between
// the selected starting date and January 1st, 2007
TimeSpan tmDifference = DateStart.Subtract(new DateTime(2007, 1, 1));
int days = tmDifference.Days;
// Now that we have the number of days,
// this number must be divisible by 14 (2 weeks)
if ((days % 14) != 0)
{
MessageBox.Show("Invalid starting period - Please try again");
EnableForInvalidDate(false);
return;
}
else
EnableForInvalidDate(true);
// Now that we have a valid starting period,
// let's help the user and select the time period
DateTime range = e.Start.AddDays(-1);
calTimeFrame.SelectionEnd = range.AddDays(14);
}
|
- Return to the form and double-click the Close button
- Implement its Click event as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
|
- Execute the application and try selecting a range of dates
- Close the form and return to your programming environment
|
The Maximum Date Range Selection |
|
To control the number of days you want the user to be able to select, change the value of the MaxSelectionCount
property. The user cannot select more days than the MaxSelectionCount
value but the user can select less.
|
Practical
Learning: Set the Maximum Range
|
|
- Return to the form and click the calendar control
- In the Properties window, click MaxSelectionCount, type 14, and
press Enter
- Save the form
|
Characteristics of a Month Calendar Control |
|
The calendar control is a rectangular object without a border. After placing it on the form, it displays the current month and only one month. This is because, by default, its width and height are set enough to accommodate only one month.
|
The Background Color of the Title Bar |
|
To make it a highly visual object, a calendar control 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 next month.
| As mentioned already, the top section of the calendar
control displays buttons and labels. By default, these are positioned on
top of a blue background. The background color of this section is
controlled by the TitleBackColor property |
 |
|
The Font Color of the Title Bar |
|
 |
By default, the labels on the title bar display in a white
color defined by the ActiveCaptionText system color. The color used
to paint the text of the labels of the title bar is controlled by the TitleForeColor
property |
|
The Minimum and Maximum Dates |
|
As mentioned already, to change month and subsequently the
year of the calendar, the user can click the buttons continuously. By default,
the user can navigate from 1/1/1753 to 12/31/9998. If you want to limit the allowable dates
beyond which the user should not navigate, use the MinDate and the MaxDate
properties.
|
The First Day of the Week |
|
Under the title bar, the short names weekdays display, using the format set in Control Panel. In US English, the first day is usually Sunday. If you want to start with a different day, set the value using the
FirstDayOfWeek property. The names of weekdays use the same color as the
TitleBackColor property. 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.
|
The Background Color of the Calendar |
|
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. This color is
controlled by the overridden BackColor property.
|
 |
|
The Font Color of the Days of the Current Month |
|
 |
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. The color of these days is
controlled by the overridden ForeColor property. |
|
|
The Font Color of the Days of the Trailing Months |
|
Besides the days of the currently selected month, the
calendar control also displays one or more days of the previous month and one or
more days of the subsequent month. These are referred to as trailing months or
trailing days. These are dayts that don't belong to the currently selected
month. These days display in a different color controlled by the TrailingForeColor
property. By default, this color is set to GrayText:

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.
|
Practical
Learning: Coloring the Month Calendar Control
|
|
- On the form, click the calendar control
- In the Properties window, change the following values:
BackColor: 255, 192, 128
ForeColor: Maroon
TitleBackColor: 192, 64, 0
TitleForeColor: Yellow
TrailingForeColor: 255, 255, 192
- Save the form
The calendar control is used to let the user know today's date in two ways. On the calendar, today's date is circled by an
almost hand-drawn ellipse. In the bottom section of the calendar, today's date is also displayed as a sentence. If you want to display or hide the bottom label, set the
ShowToday Boolean property accordingly. For example, to hide it, set this property to false.
The presence or absence of this ellipse is controlled by the ShowTodayCircle
Boolean property whose default value is True. If you set this property to
False, today's would appear without the ellipse:
When a new calendar control is added to an application, it assumes today's date.
If you want to change this date, use the TodayDate property.
|
Practical
Learning: Hiding Today
|
|
- On the form, click the calendar control and, in the Properties window,
double-click ShowToday to set its value to False
- Execute the application to test it

- Close the form and return to your programming environment
To accentuate the importance of one or more days of a month, you can bold some
days. To bold some days of the calendar, create an array that holds the days. To
visually create the list of dates, on the form, click the calendar control. In
the Properties window, click BoldDates and click the ellipsis of its field. This
would open the DateTime Collection Editor. To add a date member, you can click
Add. On the right side, there would be a field named Date. You can type the date
or you can click the arrow of the field. This would display a calendar:
You can then select a date. In the same way, to complete the array, you can
create the other dates you want. After creating the list, you can click OK.
To programmatically create the list of dates, create an array of DateTime values
(each member of the array must be a recognizable DateTime value). Once the
array is ready, assign it to the BoldDates property.
If you prefer the
months bolded, assign the array to the MonthlyBoldedDates property.
|
|