Pabo.Calendar.DateItem[] diArray = new Pabo.Calendar.DateItem[2];
Pabo.Calendar.DateItem di = new Pabo.Calendar.DateItem();
private void PaintDateBackcolor(DateTime[] dt)
{
for (int i = 0; i < dt.Length; i++)
{
diArray[i] = di;//加入DateItem
diArray[i].Date = dt[i];//設定要塗上色塊的日期
diArray[i].BackColor1 = Color.Red;//色塊顏色
}
mCal.AddDateInfo(diArray);//將日期色快加入自Canlendar中
}
//this.mCal.DaySelected += new Pabo.Calendar.DaySelectedEventHandler(this.mCal_DaySelected);
private void mCal_DaySelected(object sender, Pabo.Calendar.DaySelectedEventArgs e)
{
//顯示日期在標籤中
this.label1.Text = e.Days[0].ToString();
//將所選取的日期塗上色塊
PaintDateBackcolor(new DateTime[] { Convert.ToDateTime(e.Days[0].ToString()) });
}
private void Form1_Load(object sender, EventArgs e)
{
//將該日期塗上色塊
DateTime[] dt = new DateTime[] { new DateTime(2011, 9, 25) };
PaintDateBackcolor(dt);
//設定今天日期的顏色
mCal.TodayColor = Color.Blue;
}
Canlendar其他說明
http://www.codeproject.com/KB/selection/MonthCalendar.aspx
- Download source files (VS 2003) - 81.4 Kb
- Download demo (.NET 1.1) - 66.8 Kb
- Download source files (VS 2005) - 84.3 Kb
- Download demo (.NET 2.0) - 67.4 Kb
Introduction
I decided to write this control because I needed a month calendar that's much more customizable and flexible than the standard Visual Studio Calendar, in one of my projects. My primary focus was the ability to add information (color, text, image etc.) to each day, and for this to work reasonably well, it must also be resizable.
This is my second article for CodeProject, and it shares some of the implementation techniques of the previous article, so if you want some detail on the implementation of themes, nested properties, and TypeEditors, check out my MozBar article. For information about how to edit and persist collections, check out Daniel Zaharia's excellent article.
Using the control
Like any other .NET control, for using in the IDE, you should
add the MonthCalendar
control to the Toolbox panel. This can be
accomplished by right-clicking on a Toolbox tab and selecting "Add/Remove
items...", browsing to the MonthCalendar
assembly, and selecting it. This will add
the MonthCalendar
control to the Toolbox so that it can be
dragged/dropped to a Windows Form.
Once an instance of MonthCalendar
is added to the form, select it and view
its properties.
Layout and design
The basic design for the control is pretty much like the
standard Visual Studio Calendar
, but it is a lot more
flexible. To make it more portable and to reduce the overhead, everything is
drawn directly with GDI.MonthCalendar
basically consists of five different regions, each with its own set of
properties.
The only region that must be visible is the month region, all the others can be switched on or off.
Properties
The following properties control the most significant
behavior and the look and feel of the MonthCalendar
control:
BorderColor
: Color used for the border.BorderStyle
: The style used for the border.ShowFooter
: Indicates whether the footer should be visible (default=true).ShowHeader
: Indicates whether the header should be visible (default=true).ShowWeekdays
: Indicates whether weekdays should be visible (default=true).ShowWeeknumbers
: Indicates whether week numbers should be visible (default=false).TodayColor
: The color used for the circle that marks today's date.ActiveMonth
: The month currently shown in the calendar.Culture
: The culture used for the calendar.Dates
: A collection of formatted dates.ImageList
: TheImageList
used to hold images for the calendar, this must be set if you want to assign images to dates.MaxDate
: The maximum date that can be selected.MinDate
: The minimum date that can be selected.SelectedDates
: Collection of selected dates.SelectionMode
: Indicates the selection mode used in the calendar (None
,One
,MultiSimple
, orMultiExtended
).ExtendedSelectionKey
: The key used for the extended selection mode.FirstDayOfWeek
: Sets the first day of week for the current culture.SelectButton
: The mouse button used for selections.SelectTrailingDates
: Indicates whether selecting trailing dates is possible (default=true).ShowFocus
: Toggles hot tracking when moving the mouse over a date (default=true).ShowToday
: Indicates if today's date should be marked, the color used for the mark is the one assigned toTodayColor
(default=true).ShowTrailingDates
: Indicates whether trailing dates should be visible or not (default=true).Theme
: Indicates whether the calendar should use theme colors (default=false).KeyboardEnabled
: Indicates whether keyboard support is enabled (default=true).Keyboard
: Collection of keys used for keyboard control.Version
: Returns the version number.
Month
BackgroundImage
: Image used as background.Transparency
: Text and background transparency (used when painting colors).FormatTrailing
: Indicates whether formatting should be shown for trailing dates (default=true).Padding
: Vertical and horizontal spacing.DateAlign
: Date alignment within a day.ShowMonthInDay
: Indicates whether the first and the last day of a month should have the month displayed in the date (default=false).TextAlign
: Text alignment within a day.EnableImageClick
: Enables theImageClick
event (default=false).ImageAlign
: Image alignment within a day.DateFont
: Font used for the date.TextFont
: Font used for the text.Colors
: Collection of colors used in the calendar.BorderStyles
: Collection of border styles used in the calendar.
Header
Align
: Alignment of the month/text in the header.MonthSelectors
: Indicates whether the next/previous month button should be visible (default=true).YearSelectors
: Indicates whether the next/previous year button should be visible (default=false).ShowMonth
: Indicates if the month name should be visible in the header (default = true).Text
: The text to be displayed in the header (ifShowMonth
is false).BackColor1
: The color used for the header background.BackColor2
: The second color used for background when using a gradient.GradientMode
: Type of gradient used.Font
: The font used for the month/text.TextColor
: The color used for the month/text.MonthContextMenu
: Indicates whether a month selection menu should be displayed while right-clicking the header (default = true).
Footer
Align
: The text alignment for the footer.Text
: The text to be displayed in the footer, ifShowToday
is false.ShowToday
: Indicates whether today's date should be displayed in the footer (default=true).Format
: The format used for today's date.BackColor1
: The color used for the header background.BackColor2
: The second color used for background when using a gradient.GradientMode
: Type of gradient used.Font
: The font used for the date/text.TextColor
: The color used for the date/text.
Weekdays
BorderColor
: The color used for the border.BackColor1
: The color used for the header background.BackColor2
: The second color used for background when using a gradient.GradientMode
: Type of gradient used.Font
: The font used for weekdays.TextColor
: The color used for weekdays.Format
: The format used to display weekdays.Align
: Text alignment for weekdays.
Weeknumbers
BorderColor
: The color used for the border.BackColor1
: The color used for the header background.BackColor2
: The second color used for background when using a gradient.GradientMode
: Type of gradient used.Font
: The font used for week numbers.TextColor
: The text color used for week numbers.Align
: Text alignment for week numbers.
Events
The most useful events are:
Month
MonthChanged
: Indicates that the active month was changed.BeforeMonthChanged
: Raised before a month is displayed. Use this event to prevent the selection of certain months.DayDragDrop
: Indicates that data was dropped on a day,AllowDrop
must be true for this event to be raised.ImageClick
: Indicates that an image was clicked.DayClick
: Indicates that a day was clicked.DayRender
: Occurs before a date is updated.DayQueryInfo
: Occurs before a date is updated.DayDoubleClick
: Indicates that a day was double clicked.DaySelected
: Indicates that one or more days were selected.BeforeDaySelected
: Raised before a day is selected. Use this event to prevent selection of days.DayDeselected
: Indicates that one or more days were deselected.BeforeDayDeselected
: Raised before a day is deselected. Use this event to prevent deselection of days.DayGotFocus
: Indicates that a day received focus.DayLostFocus
: Indicates that a day lost focus.DayMouseMove
: Indicates that the mouse is moved inside a day.
Header
HeaderClick
: Indicates that the header was clicked.HeaderDoubleClick
: Indicates that the header was double clicked.HeaderMouseEnter
: Indicates that the mouse entered the header region.HeaderMouseLeave
: Indicates that the mouse left the header region.
Footer
FooterClick
: Indicates that the footer was clicked.FooterDoubleClick
: Indicates that the footer was double clicked.FooterMouseEnter
: Indicates that the mouse entered the footer region.FooterMouseLeave
: Indicates that the mouse left the footer region.
Weekday
WeekdayClick
: Indicates that a weekday was clicked.WeekdayDoubleClick
: Indicates that a weekday was double clicked.WeekdayMouseEnter
: Indicates that the mouse entered the weekday region.WeekdayMouseLeave
: Indicates that the mouse left the weekday region.
Weeknumber
WeeknumberClick
: Indicates that a week was clicked.WeeknumberDoubleClick
: Indicates that a week was double clicked.WeeknumberMouseEnter
: Indicates that the mouse entered the week number region.WeeknumberMouseLeave
: Indicates that the mouse left the week number region.
As usual, when using events, the supplied eventArgs
parameter contains the properties useful
for that particular event.
Methods
The following methods are supported:
Date formatting
- void
AddDateInfo(DateItem[] info)
: Adds an array of formatted dates. - void
RemoveDateInfo(DateTime dt)
: Removes theDateItem
associated with the supplied date. - void
RemoveDateInfo(DateItem item)
: Removes the suppliedDateItem
. - void
AddDateInfo(DateItem info)
: Adds a formatted date. - void
ResetDateInfo()
: Removes all date formatting. DateItem[] GetDateInfo()
: Returns all the formatted dates.DateItem[] GetDateInfo(DateTime dt)
: Returns an array ofDateItem
s matching the supplied date.
Selection
- void
SelectDate(DateTime d)
: Selects the supplied date. The date must be betweenMinDate
andMaxDate
. - void
ClearSelection()
: Clears the existing selection. - bool
IsSelected(DateTime dt)
: Returns true if the supplied date is selected, otherwise false. - void
SelectArea(DateItem topleft, DateItem bottomright)
: Selects the area described by the two dates. - void
DeselectArea(DateItem topleft, DateItem bottomright)
: Deselects the area described by the two dates. - void
SelectRange(DateItem from, DateItem to)
: Selects the range described by the two dates. - void
DeselectRange(DateItem from, DateItem to)
: Deselects the range described by the two dates. - void
SelectWeek(
intweek)
: Selects every day in the supplied week. - void
DeselectWeek(
intweek)
: Deselects every selected day in the supplied week. - void
SelectWeekday(DayOfWeek day)
: Selects everyDayOfWeek
in the current month. - void
DeselectWeekday(DayOfWeek day)
: Deselects every selectedDayOfWeek
in the current month.
Misc.
- void
Print()
: Prints the current calendar on the default printer. Bitmap Snapshot()
: Returns a bitmap of the current calendar.- void
SaveAsImage(
stringfilename, ImageFormat format)
: Saves the calendar to a file. - void
Copy()
: Copies the calendar to the clipboard.
Adding date formatting
You can add formatted dates either during runtime by using
one of the DateInfo
methods, or in design mode by using the built-in DateItemCollection
.
Adding date formatting in design mode is, of course, not very
practical for real applications, your info will most likely be stored in some
kind of database, so the best way to add date formatting is to respond to theMonthChanged
event and add the dates during runtime:
Collapse | Copy Code
private void monthCalendar1_MonthChanged(object sender,
Pabo.Calendar.MonthChangedEventArgs e)
{
AddInfo(e.Year,e.Month);
}
To add formatted dates during runtime, you need to create DateItem
objects. A DateItem
has several properties that define the
appearance of the date:
Date
: The date for which the info applies.BackgroundImage
: The image used as background.BackColor1
: The color used for background.BackColor2
: The second color used for background when using a gradient.GradientMode
: Type of gradient used.Weekend
: Indicates whether the date should be handled as a weekend (default = false).DateColor
: Color used for the date.TextColor
: Color used for the text.ImageListIndex
: Index for the image to be displayed in the date. For this to work, anImageList
must be assigned to theMonthCalendar
.Image
: Image to be displayed in the date. If this property is set, it will override theImageList
.BoldedDate
: Indicates if the date should use a bold font (default = false).Enabled
: Indicates whether the date is enabled or not. A date that is disabled is not selectable, and will be drawn using the disabled colors. Any image will be drawn in a disabled state (default = true).Pattern
: Describes the recurring pattern used for thisDateItem
(default =None
).Range
: Describes the maximum range (end date) for the recurring pattern.
Creating and adding DateItem
s could look something like
this:
Collapse | Copy Code
private void FormatDates()
{
DateItem[] d = new DateItem[5];
d.Initialize();
for (int i = 0;i<5;i++)
d[i] = new DateItem();
d[0].Date = new DateTime(2005,6,3);
d[0].BackColor1 = Color.Red;
d[0].ImageListIndex = 3;
d[0].Text = "Help";
d[1].Date = new DateTime(2005,6,12);
d[1].ImageListIndex = 2;
d[2].Date = new DateTime(2005,6,16);
d[2].BackColor1 = Color.LightBlue;
d[2].ImageListIndex = 8;
d[3].Date = new DateTime(2005,6,18);
d[3].BackColor1 = Color.GreenYellow;
d[3].ImageListIndex = 1;
d[3].Text = "NorDev";
d[4].Date = new DateTime(2005,6,22);
d[4].ImageListIndex = 1;
d[4].Text = "Cebit";
monthCalendar1.AddDateInfo(d);
}
If you don't want to add a lot of DateItem
s at once, you can use the DayQueryInfo
event and add formatting depending on the
date. The DayQueryInfo
event is raised before each date is
rendered, and makes it possible to supply date formatting using the DateItem
properties.
Collapse | Copy Code
private void monthCalendar1_DayQueryInfo(object sender,
DayQueryInfoEventArgs e)
{
// Check date
if (e.Date.DayOfWeek == DayOfWeek.Thursday)
{
// Add custom formatting
e.Info.BackColor1 = Color.Yellow;
e.Info.BackColor2 = Color.GhostWhite;
e.Info.ImageListIndex = 3;
e.Info.GradientMode = mcGradientMode.Horizontal;
// Set ownerdraw = true to add custom formatting
e.OwnerDraw = true;
}
}
Note that you must set OwnerDraw
=true to add formatting, and the formatting added by this event is overridden
by the DayRender
event if that is used.
Recurring dates
MonthCalendar
supports basic recurring date formatting. This functionality is
controlled by the Pattern
andRange
properties.
The following patterns can be applied to a DateItem
:
None
: No recurring pattern is applied (default), the formatting is only valid for the day specified by theDate
property.Daily
: The formatting will be applied to every day within theRange
.Weekly
: The formatting will be applied to every same weekday within theRange
.Monthly
: The formatting will be applied to the same day each month within theRange
.Yearly
: The formatting will be applied to the same day every year within theRange
.
Note that there is no "collision detection", so
overlapping patterns will be drawn on top of each other. You can use functions
like GetDateInfo
to check which DateItem
s are applied to a certain
date. The Range
andPattern
properties do not have any impact when set through the DayQueryInfo
event.
Owner-drawn dates
If the built-in formatting doesn't give you the appearance
you want, then you can provide your own by using theDayRender
event. The DayRender
event is raised before each date in the
calendar is painted. You can control the contents and formatting of a date by
providing code in the event handler for the DayRender
event. To make the date owner-drawn, set DayRenderEventArs.OwnerDraw=true
:
Collapse | Copy Code
private void monthCalendar1_DayRender(object sender,
Pabo.Calendar.DayRenderEventArgs e)
{
Brush bgBrush = new SolidBrush(Color.White);
Brush dateBrush = new SolidBrush(Color.Black);
Font dateFont = new Font("Microsoft Sans Serif",(float)8.25);
StringFormat dateAlign = new StringFormat();
dateAlign.Alignment = StringAlignment.Far;
dateAlign.LineAlignment = StringAlignment.Near;
Rectangle rect = new Rectangle(0,0,e.Width,e.Height);
// Set OwnerDraw = true to override built in formatting...
e.OwnerDraw = true;
// ...then Draw the appearance of the date
e.Graphics.FillRectangle(bgBrush,rect);
e.Graphics.DrawString(e.Date.Day.ToString(),
dateFont,dateBrush,rect,dateAlign);
// Clean up
bgBrush.Dispose();
dateBrush.Dispose();
dateAlign.Dispose();
dateFont.Dispose();
}
Note that using the DayRender
event to draw the appearance of a date
completely overrides all other formatting done by the control for the specific
date.
Multi-select ala Excel
One thing I wanted to add to the control was multi-select. The problem with this is that when selected days have different colors for border and background, then it doesn't look very nice drawing all the selected days individually, and drawing the days as selected will also cover the previous backcolor; so what you have to do is draw the entire selected area with one transparent background and one border ala Excel. So, how can we do this?
It's pretty simple. The month region basically consists of an
array of days, each with its own rectangle, so what we need is the start and
the end day for the selection so that we can construct our
"selection" rectangle. When the user clicks on a day, we set the
start day (m_selStart
). And when the mouse is pressed and moved over a new day (that can be
selected), we set the end day (m_selEnd
). When drawing the selection, we only need to get the coordinates for
the selection area and draw it with the desired transparent color.
Collapse | Copy Code
// Check if an selection exist
if (m_selectedDays.Length>0)
{
Brush selBrush = new SolidBrush(Color.FromArgb(125,
Colors.SelectedBackground));
// Get Coordinates for selection rectangle
m_selRight = System.Math.Max(m_days[m_selStop].Rectangle.Right,
m_days[m_selStart].Rectangle.Right);
m_selLeft = System.Math.Min(m_days[m_selStop].Rectangle.Left,
m_days[m_selStart].Rectangle.Left);
m_selTop = System.Math.Min(m_days[m_selStop].Rectangle.Top,
m_days[m_selStart].Rectangle.Top);
m_selBottom = System.Math.Max(m_days[m_selStop].Rectangle.Bottom,
m_days[m_selStart].Rectangle.Bottom);
// Draw selection
Rectangle selRect = new Rectangle(m_selLeft,m_selTop,
m_selRight-m_selLeft,m_selBottom-m_selTop);
e.FillRectangle(selBrush,selRect);
ControlPaint.DrawBorder(e,selRect,Colors.SelectedBorder,
BorderStyles.Selected);
selBrush.Dispose();
}
Easy indeed, but I think it adds a nice touch to the control.
Different selection modes
MonthCalendar
supports the following selection modes indicated by the SelectionMode
property:
None
: No selection is possible.One
: Only one date can be selected at a time.MultiSimple
: A continuous block of dates can be selected.MultiExtended
: Same asMultiSimple
, but pressing a key enables selection/deselection of discontinuous dates. You can set the key used, with theExtendedSelectionKey
property.
When selecting/deselecting dates in code, make sure that the
appropriate SelectionMode
is set; when deselecting more than one
date, it must be set to MultiExtended
, and when selecting
more than one date, at least MultiSimple
is required.
Retrieving selected/deselected days
When selecting/deselecting dates, the DaySelected
and DayDeselected
events are raised. To retrieve the days,
you can either use the information contained in the DaySelectedEventArgs
, or use theSelectedDates
collection. Getting the dates selected by
the user could look something like this:
Collapse | Copy Code
private void monthCalendar1_DaySelected(object sender,
Pabo.Calendar.DaySelectedEventArgs e)
{
// Using the days from the EventArgs
string[] m_daysSelected = e.Days;
// Using SelectedDates
SelectedDatesCollection m_dates = monthCalendar1.SelectedDates;
}
Dynamically created dropdown in PropertyGrid
Sometimes, you want to provide the user with a list of possible choices for a property. One way to do this is to use enumerations which automatically provide you with a dropdown with the possible choices. But this solution is static, the list will always have the same content. What if you want the choices to change depending on other choices the user makes?
The solution is to create a custom TypeConverter
and override some functions that will let
us supply our own values through the StandardValuesCollection
.
GetStandardValuesSupported
decides if standard values are supported. Returning true means it's supported:
Collapse | Copy Code
public override bool GetStandardValuesSupported(
ITypeDescriptorContext context)
{
// return true to allow standard values.
return true;
}
GetStandardValuesExclusive
decides if the user should be allowed to type values or not. Returning falsemeans
typing is allowed:
Collapse | Copy Code
public override bool GetStandardValuesExclusive(
ITypeDescriptorContext context)
{
// Allow user to enter values with keyboard
return false;
}
Now, all we have to do is override GetStandardValuesCollection
and return the list that we want to use:
Collapse | Copy Code
public override System.ComponentModel.TypeConverter.StandardValuesCollection
GetStandardValues(ITypeDescriptorContext context)
{
activeMonth m = (activeMonth)context.Instance;
return new StandardValuesCollection(m.Calendar.AllowedYears());
}
You will also need to override OnConvertFrom
and OnConvertTo
to validate the input, and if you don't
inherit from StringConverter
, you
must override CanConvertFrom
and CanConvertTo
as well.
Week number
Calculating week number is somewhat problematic since
different countries in the world have different rules associated with their
calendars. In most parts of Europe, we
calculate week number according to the ISO8601 calendar, which means we use the
FirstFourDayWeek rule and Monday as the first day of the week. Using these
settings and the Swedish culture with the GetWeekOfYear
function found inSystem.Globalization.Calendar
doesn't always give you the correct week (according to ISO8601), so it
seems there are bugs in the .NET week calculation routines.
Looking around, I found a webpage that describes this problem in more detail, and even better, provides a function that works:
Collapse | Copy Code
private int GetISO8601WeekNumber(DateTime date)
{
// Calculates the ISO 8601 Weeknumber
// In this scenario the first day of the week is monday,
// and the week rule states that:
// [...] the first calendar week of a year is the one
// that includes the first Thursday of that year and
// [...] the last calendar week of a calendar year is
// the week immediately preceding the first
// calendar week of the next year.
// The first week of the year may thus start in the
// preceding year
const int JAN = 1;
const int DEC = 12;
const int LASTDAYOFDEC = 31;
const int FIRSTDAYOFJAN = 1;
const int THURSDAY = 4;
bool Week53Flag = false;
// Get the day number since the beginning of the year
int DayOfYear = date.DayOfYear;
// Get the numeric weekday of the first day of the
// year (using sunday as FirstDay)
int StartWeekDayOfYear =
(int)(new DateTime(date.Year, JAN, FIRSTDAYOFJAN)).DayOfWeek;
int EndWeekDayOfYear =
(int)(new DateTime(date.Year, DEC, LASTDAYOFDEC)).DayOfWeek;
// Compensate for the fact that we are using monday
// as the first day of the week
if (m_calendar.m_dateTimeFormat.FirstDayOfWeek!=0)
{
//if( StartWeekDayOfYear == 0)
StartWeekDayOfYear = 8 - StartWeekDayOfYear;
//if( EndWeekDayOfYear == 0)
EndWeekDayOfYear = 8 - EndWeekDayOfYear;
}
// Calculate the number of days in the first and last week
int DaysInFirstWeek = 8 - (StartWeekDayOfYear );
int DaysInLastWeek = 8 - (EndWeekDayOfYear );
// If the year either starts or ends on a
// thursday it will have a 53rd week
if (StartWeekDayOfYear == THURSDAY ||
EndWeekDayOfYear == THURSDAY)
Week53Flag = true;
// We begin by calculating the number of FULL
// weeks between the start of the year and
// our date. The number is rounded up, so the
// smallest possible value is 0.
int FullWeeks =
(int) Math.Ceiling((DayOfYear - (DaysInFirstWeek))/7.0);
int WeekNumber = FullWeeks;
// If the first week of the year has at least four days,
// then the actual week number for our date
// can be incremented by one.
if (DaysInFirstWeek >= THURSDAY)
WeekNumber = WeekNumber +1;
// If week number is larger than week 52 (and the year
// doesn't either start or end on a thursday)
// then the correct week number is 1.
if (WeekNumber > 52 && !Week53Flag)
WeekNumber = 1;
// If week number is still 0, it means that we are trying
// to evaluate the week number for a
// week that belongs in the previous year (since that week
// has 3 days or less in our date's year).
// We therefore make a recursive call using the last day of
// the previous year.
if (WeekNumber == 0)
WeekNumber = GetISO8601WeekNumber(
new DateTime(date.Year-1, DEC, LASTDAYOFDEC));
return WeekNumber;
}
If you use the ISO8601 calendar (most of Europe), MonthCalendar
will give you a correct week, if not, you
will get the Microsoft week that might be right or wrong depending on your
culture setting.
Using a callback to calculate week number
If you don't get the correct week, all hope is not lost, you
can override the calendar's standard week routines and supply your own callback
function that calculates the week numbers through the WeeknumberCallback
property. The callback
function must take a DateTime
as the only parameter, and return an
integer:
Collapse | Copy Code
public int GetWeek(DateTime dt)
{
// Calculate weeknumber here
}
If the above function is our callback, setting it up could look something like this:
Collapse | Copy Code
private void Form1_Load(object sender, System.EventArgs e)
{
monthCalendar1.WeeknumberCallBack =
new WeekCallBack(this.GetWeek);
}
Known problems/issues
- Since
this control uses an
ImageList
, it suffers from the infamous ImageList bug that destroys the alpha channel for 32 bit images when you add images to theImageList
in design mode. Workarounds for this could be to replace theImageList
with a control like theImageSet
by Tom Guinter (that is availablehere), or to add the images at run time. This is, hopefully, fixed in Visual Studio 2005 so it might not be worth the hassle.
Conclusion
I hope this control can be of use to you. I'm sure there is plenty of room for improvements and added functionality, so if you have any ideas or suggestions, please post a comment.
History
- 16th August, 2006 - Version 1.8.2
- Fixed problem with yearly pattern calculation.
- Fixed
problem with the
BeforeDayDeselected
event not being raised properly. - Fixed
problem with the
SelectedDates
collection not being updated properly. - Other fixes.
- 19th June, 2006 - Version 1.8.1
- Fixed problem with min-maxdate and header buttons.
- Fixed
a problem with the
BeforeMonthChanged
event.
- 6th June, 2006 - Version 1.8.0
- Modified ISO8601 week number calculation.
- Added keyboard support.
- Added
the
BeforeMonthChanged
event, makes it possible to prevent the selection of certain months. - Added
the
BeforeDaySelected
event. - Added
the
BeforeDayDeselected
event. - Added gradient support to almost all backgrounds.
- Header buttons are now rendered with visual styles when possible (VS2005 only).
- Added
Sunday
andSaturday
properties to weekend colors. - Added
the
DateItem.BackgroundImage
property. - Added
the
QueryDayInfo
event (see article). - Other fixes.
- 4th April, 2006 - Version 1.7.0
- Added
the
Weeknumber.Align
property. - Added
the
SelectedDates
collection. - Added
the
Month.EnableImageClick
property and theImageClick
event. - Added
the
DayMouseMove
event. - Added
mouse coordinates to
DayClick
events. - Other fixes.
- Added
the
- 17th January, 2006 - Version 1.6.0
- Fixed
the problem with
DateItemCollection
not working properly in design mode. - Added
the
FirstDayOfWeek
property. - Added
the
Header.MonthContextMenu
property. - Renamed
the old
DateItem.Image
property toDateItem.ImageListIndex
, and added a newDateItem.Image
property to allow the assignment of images without using anImageList
. - Proper default size when first placed on the form.
- Calendar
is now updated when the
CollectionEditor
(DateItem
s) is closed. - Keyboard
hook is only active when
SelectionMode = MultiExtendend
andExtendedSelectionKey != None
. - Added
the
Month.BackgroundImage
property. - Changed
the
Month.Transparency
toMonth.Transparency.Text
andMonth.Transparency.Background
. - Other fixes.
- First release for VS2005 and NET 2.0.
- Fixed
the problem with
- 25th October, 2005 - Version 1.5.0
- Added
the
DayRender
event (see article). - Added
the
YearSelectors
to the header, replaced theHeader.ShowSelectors
property withHeader.YearSelectors
andHeader.MonthSelector
properties. - Added
the
SaveAsImage
method. - Added
the
Copy
method. - Added
the
ExtendedSelectionKey
property. - Added more aligns for date, text, and image.
- Fixed
a problem with the
ShowToday
property (again..).
- Added
the
- 1st October, 2005 - Version 1.4.1.0
- Fixed
the problem with the
SelectionMode
default value. - Fixed
the problem with the
MonthChanged
event being raised twice when changing years using the Next/Previous buttons. - Fixed
the problem where
SelectDate
didn't work whenSelectionMode = One
. - Fixed
the the problem with not being able to change the
ShowToday
property. - Fixed
the problem with
FocusDate
andFocusText
being applied even ifShowFocus
was false. - Removed unnecessary painting which could cause high CPU usage.
- Fixed
the serialization problem with
WeekNumberCallBack
.
- Fixed
the problem with the
- 24th August, 2005 - Version 1.4.0.0
- Added
support for recurring dates (
None
,Daily
,Weekly
,Monthly
, andYearly
). GetDateInfo
now returns an array of matchingDateIem
s.- Added
an overload for
RemoveDateItem
that takes aDateItem
as parameter. - Fixed bug where Next/Previous buttons didn't update when min/max date is changed.
- Replaced
the
MultiSelect
property with theSelectionMode
property. - Added discontinuous multiple select (press and hold CTRL when selecting dates).
SelectDate
now raises theDaySelected
event.- Added
some customizable colors:
SelectText
,SelectDate
,FocusText
, andFocusDate
. - Added
the
IsSelected
function. - Fixed skipping months problem when using the Next/Previous buttons.
- Implemented callback for retrieving week numbers.
- Added
the
SelectArea
,DeselectArea
,SelectRange
, andDeselectRange
methods. - Added
the
SelectWeek
,DeselectWeek
,SelectWeekDay
, andDeselectWeekDay
methods.
- Added
support for recurring dates (
- 12th July, 2005 - Version 1.3.0.0
- Added
more design time support by implementing
[DefaultValue]
. - Fixed
bug that caused changes made to some properties (
ActiveMonth
,Month.BorderStyle
, andMonth.Color
) during design time to not persist. - Fixed problem with padding.
- Fixed
bug where the today marker would be drawn on a trailing date even if
ShowTrailingDates
is set to false. - Existing selection is now cleared when month is changed.
- Added
the
DayDeselected
event. - Added
the
ClearSelection
method. - Fixed problem with today marker alignment.
- Added
more design time support by implementing
- 8th July, 2005 - Version 1.2.0.0
- Added
print support (
Print
method). - Added
Snaphot
function, returns a bitmap of the current calendar. - Fixed bug that made the color for the selected border the same as the color for the selected background when using themes.
- Fixed
bug where formatted dates created during runtime would not get their
Calendar
property set. - Added
several customizable colors:
Date
,TrailingDate
,WeekendDate
,WeekendText
,DisabledBackground
,DisabledDate
, andDisabledText
. - Added support for bolded dates.
- Added support for disabled dates.
- Added
print support (
- 30th June, 2005 - Version 1.1.0.0
- Fixed the bug where the year wouldn't get updated when the Next/Previous buttons were used.
- Fixed
the bug where the month didn't redraw when
Culture
was changed.
- 29th June, 2005 - Version 1.0.0.0
- First release.
License
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here