// darws a single part of the month calendar (with one month) 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); } }