|
Hi everybody, I have a little problem. I found this example of extended monthCalendar, which has some background of day painted another color. On system winXP goes well, but on system Vista particular days have wrong position. Does anyone know, how can I resolve this problem? Thanks Ondrej
Code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Collections; using System.Threading;
namespace Calendar { public partial class RegnumCalendar : MonthCalendar { private ArrayList warningDates = new ArrayList();
public enum SelectionType { Dovolena = 1, Vikend = 2 }
public RegnumCalendar() { //SetStyle(ControlStyles.UserPaint,true); InitializeComponent(); warningDates.Add(new DateTime(2007, 12, 1)); warningDates.Add(new DateTime(2007, 12, 20)); warningDates.Add(new DateTime(2007, 12, 31)); }
public void addNewDate(ArrayList list) { this.warningDates.AddRange(list); Graphics graphics = Graphics.FromHwnd(this.Handle); PaintEventArgs pe = new PaintEventArgs(graphics, new Rectangle(0, 0, this.Width, this.Height)); OnPaint(pe); }
// Override WndProc and force a call to OnPaint when we get a WM_PAINT protected static int WM_PAINT = 0x000F; protected static int WM_RBUTTONUP = 0x0205;
protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == WM_RBUTTONUP) { //showContextMenu(); m.Result = IntPtr.Zero; //return; } base.WndProc(ref m); if (m.Msg == WM_PAINT) { Graphics graphics = Graphics.FromHwnd(this.Handle); PaintEventArgs pe = new PaintEventArgs(graphics, new Rectangle(0, 0, this.Width, this.Height)); OnPaint(pe); } }
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e);
Graphics graphics = e.Graphics; int dayBoxWidth = 0; int dayBoxHeight = 0; float dayBoxWidthF = 0; float dayBoxHeightF = 0; int firstWeekPosition = 0; int lastWeekPosition = Height;
if (warningDates.Count > 0) { SelectionRange calendarRange = GetDisplayRange(false);
// Create a list of those dates that actually should be marked as warnings. ArrayList visibleWarningDates = new ArrayList(); foreach (DateTime date in warningDates) { if (date >= calendarRange.Start && date <= calendarRange.End) { visibleWarningDates.Add(date); } } if (visibleWarningDates.Count > 0) { while ((HitTest(25, firstWeekPosition).HitArea != HitArea.PrevMonthDate && HitTest(25, firstWeekPosition).HitArea != HitArea.Date) && firstWeekPosition < Height) { firstWeekPosition++; }
while ((HitTest(25, lastWeekPosition).HitArea != HitArea.NextMonthDate && HitTest(25, lastWeekPosition).HitArea != HitArea.Date) && lastWeekPosition >= 0) { lastWeekPosition--; }
if (firstWeekPosition > 0 && lastWeekPosition > 0) { dayBoxWidth = Width / (ShowWeekNumbers ? 8 : 7); dayBoxWidthF = Width / (ShowWeekNumbers ? 8.0f : 7.0f); dayBoxHeight = (int)(((float)(lastWeekPosition - firstWeekPosition)) / 6.0f); dayBoxHeightF = ((float)(lastWeekPosition - firstWeekPosition)) / 6.0f; //dayBoxHeightF = Height / 9; using (Brush warningBrush = new SolidBrush(Color.FromArgb(255, Color.Red)))//.FromArgb(255, 240, 240)))) { foreach (DateTime visDate in visibleWarningDates) { int row = 0; int col = 0;
TimeSpan span = visDate.Subtract(calendarRange.Start); row = span.Days / 7; col = span.Days % 7;
Rectangle fillRect = new Rectangle((col + (ShowWeekNumbers ? 1 : 0)) * dayBoxWidth + 2, firstWeekPosition + row * dayBoxHeight + 2, dayBoxWidth -2, dayBoxHeight -2); Rectangle fillRectF = new Rectangle((int)Math.Round((col + (ShowWeekNumbers ? 1 : 0)) * dayBoxWidthF,0)+2, (int)(firstWeekPosition + row * dayBoxHeightF)+1, (int)dayBoxWidthF-2, (int)dayBoxHeightF+1); graphics.FillRectangle(warningBrush, fillRect); //graphics.FillRectangle(warningBrush, ((col + (ShowWeekNumbers ? 1 : 0)) * dayBoxWidthF) + 2, (firstWeekPosition + row * dayBoxHeightF) + 1, dayBoxWidthF - 2, dayBoxHeightF + 1);
// Check if the date is in the bolded dates array bool makeDateBolded = false; foreach (DateTime boldDate in BoldedDates) { if (boldDate == visDate) { makeDateBolded = true; } }
using (Font textFont = new Font(Font, (makeDateBolded ? FontStyle.Bold : FontStyle.Regular))) { TextRenderer.DrawText(graphics, visDate.Day.ToString(), textFont, fillRect, Color.FromArgb(255, 128, 0, 0), TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter); } } } } } } } } }
| | Zenisek Ondrej Wednesday, January 02, 2008 9:23 AM | I tried comment this //Application.EnableVisualStyles(); and after that it is ok, only monthcalendar has other look.
| | Zenisek Ondrej Wednesday, January 02, 2008 11:55 AM | I tried comment this //Application.EnableVisualStyles(); and after that it is ok, only monthcalendar has other look.
| | Zenisek Ondrej Wednesday, January 02, 2008 11:55 AM | Hi all, This is my first post on MSDN! I was looking for a MonthCalendar able to highlight several important days... The BoldedDates property was good for this but not enough visible for the user! I found this code and I notice it was just working in single month view. When the MonthCalendar.Dock property is set to "Fill" the code doesn't work anymore or the behavior was unpredictable when several months were displayed... The same issue arrives when the font size is modified. I did not want to use an Open Source component as we can see when we search "Extended month calendar" trough the web... Just want to upgrade the existing one and i found this code and modified it. Feel free to use and abuse it! public partial class ExtendedCalendar : MonthCalendar { //Default Colors for the hilghlighted days private Color highLightBackColor = Color.Red; private Color highLightForeColor = Color.Black; public ExtendedCalendar() { InitializeComponent(); } //Property for the back color of high light days public Color HighLightBackColor { get { return highLightBackColor; } set { highLightBackColor = value; } } //Property for the fore color of high light days public Color HighLightForeColor { get { return highLightForeColor; } set { highLightForeColor = value; } } // Override WndProc and force a call to OnPaint when we get a WM_PAINT protected static int WM_PAINT = 0x000F; protected static int WM_RBUTTONUP = 0x0205; protected override void OnResize(EventArgs e) { base.OnResize(e); Refresh(); Graphics graphics = Graphics.FromHwnd(this.Handle); PaintEventArgs pe = new PaintEventArgs(graphics, new Rectangle(0, 0, this.Width, this.Height)); OnPaint(pe); } protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == WM_RBUTTONUP) { //showContextMenu(); m.Result = IntPtr.Zero; //return; } base.WndProc(ref m); if (m.Msg == WM_PAINT) { Graphics graphics = Graphics.FromHwnd(this.Handle); PaintEventArgs pe = new PaintEventArgs(graphics, new Rectangle(0, 0, this.Width, this.Height)); OnPaint(pe); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics graphics = e.Graphics; int dayBoxWidth = 0; int dayBoxHeight = 0; int xPosition = 0; int yPosition = 0; if (BoldedDates.Count() > 0) { SelectionRange calendarRange = GetDisplayRange(true); // Create a list of those dates that actually should be marked as warnings. ArrayList visibleWarningDates = new ArrayList(); foreach (DateTime date in BoldedDates) { if (date >= calendarRange.Start && date <= calendarRange.End) { visibleWarningDates.Add(date); } } if (visibleWarningDates.Count > 0) { //Get the font heigth to be font size independant int fHeight = this.Font.Height; //Coordinate to be sure to hit a calendar vertically and horizontally //The middle of the component is not ok for the 2*2 month dispositions //that's why I substract a quarter of one calendar size! int hitHeigth = (Height / 2) - (SingleMonthSize.Height / 4); int hitWidth = (Width / 2) - (SingleMonthSize.Width / 4); int halfWidth = Width / 2; int halfHeight = Height / 2; //Searching the x and y distance between component border and the calendar displayed! //Sometimes after resizing the HitTest fail to return real values, //stopping at the half height & width to avoid no end loops while (HitTest(hitWidth, yPosition).HitArea == HitArea.Nowhere && yPosition < halfHeight) yPosition++; while (HitTest(xPosition, hitHeigth).HitArea == HitArea.Nowhere && xPosition < halfWidth) xPosition++; //Calculate the total of month displayed int totalMonths = ((calendarRange.End.Year - calendarRange.Start.Year) * 12) + calendarRange.End.Month + 1 - calendarRange.Start.Month; int calMonthWidth = 1; //Calculate the real CalendarDimensions! if (CalendarDimensions.Width * CalendarDimensions.Height > 1) { //The group of month is centered vertically and horizontally //That's why i choose to multiply the yPosition by 2 //If the font Heigth is not added on one hand an substracted on the other hand, the calcul can be wrong! int realHeigth = CalendarDimensions.Height - ((yPosition * 2 + fHeight) / (SingleMonthSize.Height - fHeight)); calMonthWidth = totalMonths / (realHeigth == 0 ? 1 : realHeigth); //Be sure calMonthWidth is not equal to 0 to avoid division by 0 exception! calMonthWidth = (calMonthWidth == 0 ? 1 : calMonthWidth); } //Setting proportions of a dayBox //Fotunately it's proportionnal to the SingleMonthSize and the font Height dayBoxWidth = this.SingleMonthSize.Width / (ShowWeekNumbers ? 8 : 7); dayBoxHeight = (int)((this.SingleMonthSize.Height - fHeight) / 9); using (Brush warningBrush = new SolidBrush(Color.FromArgb(255, highLightBackColor))) { foreach (DateTime visDate in visibleWarningDates) { int row = 0; int col = 0; //Calculate the absolute position of the month containing the visDate int posMonth = ((visDate.Year - calendarRange.Start.Year) * 12) + visDate.Month - calendarRange.Start.Month; //Dividing it into col and row position int monthRow = posMonth / calMonthWidth; int monthCol = posMonth % calMonthWidth; //Calculating the difference between the date and the first date in the month DateTime firsDateOfMonth = new DateTime(visDate.Year, visDate.Month, 1); //Looking for the firs day in the week for the current culture DayOfWeek firstDay = Application.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //Calculating the position of the date in the month TimeSpan span = visDate.Subtract(firsDateOfMonth.AddDays(-((int)firsDateOfMonth.DayOfWeek) + (int)firstDay)); //DayOfWeek enum is starting at Sunday ( = 0) solving the problem for other cultures if ((int)firstDay != 0 && (int)firsDateOfMonth.DayOfWeek == 0) span = span.Add(new TimeSpan(7, 0, 0, 0)); //Calculating the row and the column in the month row = span.Days / 7; col = span.Days % 7; //Creating the rectangle to draw the highlight days //xPosition and yPosition represent the top left corner of the group of months //SingleMonthSize with monthRow and monthCol let me aim the top left corner of the particular month of the visDate //col and row are used to calculate the final position in the month //dayBoxWidth & dayBoxHeight define the size of the rectangle Rectangle fillRect = new Rectangle( xPosition + (monthCol * (SingleMonthSize.Width + 6)) + ((col + (ShowWeekNumbers ? 1 : 0)) * dayBoxWidth + 1), yPosition + (monthRow * (SingleMonthSize.Height - (fHeight - 2))) + (row * dayBoxHeight + ((SingleMonthSize.Height - fHeight) / 3)), dayBoxWidth - 2, dayBoxHeight - 2 ); graphics.FillRectangle(warningBrush, fillRect); //Uncomment following code if you are not using BoldedDates and switch the "using" // Check if the date is in the bolded dates array //bool makeDateBolded = false; //if (BoldedDates.Contains(visDate)) // makeDateBolded = true; //using (Font textFont = new Font(Font, (makeDateBolded == true ? FontStyle.Bold: FontStyle.Regular))) using (Font textFont = new Font(Font, FontStyle.Bold)) { TextRenderer.DrawText(graphics, visDate.Day.ToString(), textFont, fillRect, highLightForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter); } } } } } } } | | Mad Piou Monday, September 14, 2009 12:33 PM |
|