private void DrawSingleMonth(Graphics dc, Rectangle clip_rectangle, Rectangle rectangle, MonthCalendar mc, int row, int col)
{
// cache local copies of Marshal-by-ref internal members (gets around error CS0197)
Size title_size = (Size)((object)mc.title_size);
Size date_cell_size = (Size)((object)mc.date_cell_size);
DateTime current_month = (DateTime)((object)mc.current_month);
DateTime sunday = new DateTime(2006, 10, 1);
// draw the title back ground
DateTime this_month = current_month.AddMonths (row*mc.CalendarDimensions.Width+col);
Rectangle title_rect = new Rectangle(rectangle.X, rectangle.Y, title_size.Width, title_size.Height);
if (title_rect.IntersectsWith (clip_rectangle)) {
dc.FillRectangle (ResPool.GetSolidBrush (mc.TitleBackColor), title_rect);
// draw the title
string title_text = this_month.ToString ("MMMM yyyy");
dc.DrawString (title_text, mc.bold_font, ResPool.GetSolidBrush (mc.TitleForeColor), title_rect, mc.centered_format);
if (mc.ShowYearUpDown) {
Rectangle year_rect;
Rectangle upRect, downRect;
ButtonState upState, downState;
mc.GetYearNameRectangles (title_rect, row * mc.CalendarDimensions.Width + col, out year_rect, out upRect, out downRect);
dc.FillRectangle (ResPool.GetSolidBrush (SystemColors.Control), year_rect);
dc.DrawString (this_month.ToString ("yyyy"), mc.bold_font, ResPool.GetSolidBrush (Color.Black), year_rect, mc.centered_format);
upState = mc.IsYearGoingUp ? ButtonState.Pushed : ButtonState.Normal;
downState = mc.IsYearGoingDown ? ButtonState.Pushed : ButtonState.Normal;
ControlPaint.DrawScrollButton (dc, upRect, ScrollButton.Up, upState);
ControlPaint.DrawScrollButton (dc, downRect, ScrollButton.Down, downState);
}
// draw previous and next buttons if it's time
if (row == 0 && col == 0)
{
// draw previous button
DrawMonthCalendarButton (
dc,
rectangle,
mc,
title_size,
mc.button_x_offset,
(System.Drawing.Size)((object)mc.button_size),
true);
}
if (row == 0 && col == mc.CalendarDimensions.Width-1)
{
// draw next button
DrawMonthCalendarButton (
dc,
rectangle,
mc,
title_size,
mc.button_x_offset,
(System.Drawing.Size)((object)mc.button_size),
false);
}
}
// set the week offset and draw week nums if needed
int col_offset = (mc.ShowWeekNumbers) ? 1 : 0;
Rectangle day_name_rect = new Rectangle(
rectangle.X,
rectangle.Y + title_size.Height,
(7 + col_offset) * date_cell_size.Width,
date_cell_size.Height);
if (day_name_rect.IntersectsWith (clip_rectangle)) {
dc.FillRectangle (GetControlBackBrush (mc.BackColor), day_name_rect);
// draw the day names
DayOfWeek first_day_of_week = mc.GetDayOfWeek(mc.FirstDayOfWeek);
for (int i=0; i < 7; i++)
{
int position = i - (int) first_day_of_week;
if (position < 0)
{
position = 7 + position;
}
// draw it
Rectangle day_rect = new Rectangle(
day_name_rect.X + ((i + col_offset)* date_cell_size.Width),
day_name_rect.Y,
date_cell_size.Width,
date_cell_size.Height);
dc.DrawString (sunday.AddDays (i + (int) first_day_of_week).ToString ("ddd"), mc.Font, ResPool.GetSolidBrush (mc.TitleBackColor), day_rect, mc.centered_format);
}
// draw the vertical divider
int vert_divider_y = Math.Max(title_size.Height+ date_cell_size.Height-1, 0);
dc.DrawLine (
ResPool.GetPen (mc.ForeColor),
rectangle.X + (col_offset * date_cell_size.Width) + mc.divider_line_offset,
rectangle.Y + vert_divider_y,
rectangle.Right - mc.divider_line_offset,
rectangle.Y + vert_divider_y);
}
// draw the actual date items in the grid (including the week numbers)
Rectangle date_rect = new Rectangle (
rectangle.X,
rectangle.Y + title_size.Height + date_cell_size.Height,
date_cell_size.Width,
date_cell_size.Height);
int month_row_count = 0;
bool draw_week_num_divider = false;
DateTime current_date = mc.GetFirstDateInMonthGrid ( new DateTime (this_month.Year, this_month.Month, 1));
for (int i=0; i < 6; i++)
{
// establish if this row is in our clip_area
Rectangle row_rect = new Rectangle (
rectangle.X,
rectangle.Y + title_size.Height + (date_cell_size.Height * (i+1)),
date_cell_size.Width * 7,
date_cell_size.Height);
if (mc.ShowWeekNumbers) {
row_rect.Width += date_cell_size.Width;
}
bool draw_row = row_rect.IntersectsWith (clip_rectangle);
if (draw_row) {
dc.FillRectangle (GetControlBackBrush (mc.BackColor), row_rect);
}
// establish if this is a valid week to draw
if (mc.IsValidWeekToDraw (this_month, current_date, row, col)) {
month_row_count = i;
}
// draw the week number if required
if (mc.ShowWeekNumbers && month_row_count == i) {
if (!draw_week_num_divider) {
draw_week_num_divider = draw_row;
}
// get the week for this row
int week = mc.GetWeekOfYear (current_date);
if (draw_row) {
dc.DrawString (
week.ToString(),
mc.Font,
ResPool.GetSolidBrush (mc.TitleBackColor),
date_rect,
mc.centered_format);
}
date_rect.Offset(date_cell_size.Width, 0);
}
// only draw the days if we have to
if(month_row_count == i) {
for (int j=0; j < 7; j++)
{
if (draw_row) {
DrawMonthCalendarDate (
dc,
date_rect,
mc,
current_date,
this_month,
row,
col);
}
// move the day on
current_date = current_date.AddDays(1);
date_rect.Offset(date_cell_size.Width, 0);
}
// shift the rectangle down one row
int offset = (mc.ShowWeekNumbers) ? -8 : -7;
date_rect.Offset(offset*date_cell_size.Width, date_cell_size.Height);
}
}
// month_row_count is zero based, so add one
month_row_count++;
// draw week numbers if required
if (draw_week_num_divider) {
col_offset = 1;
dc.DrawLine (
ResPool.GetPen (mc.ForeColor),
rectangle.X + date_cell_size.Width - 1,
rectangle.Y + title_size.Height + date_cell_size.Height + mc.divider_line_offset,
rectangle.X + date_cell_size.Width - 1,
rectangle.Y + title_size.Height + date_cell_size.Height + (month_row_count * date_cell_size.Height) - mc.divider_line_offset);
}
}