2 // System.Windows.Forms.DateTimePicker.cs
5 // stubbed out by Richard Baumann (biochem333@nyc.rr.com)
6 // Dennis Hayes (dennish@Raytek.com)
7 // Aleksey Ryabchuk (ryabchuk@yahoo.com)
9 // (C) Ximian, Inc., 2002/3
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.ComponentModel
;
34 using System
.Runtime
.InteropServices
;
36 namespace System
.Windows
.Forms
{
39 // Represents a Windows date-time picker control.
41 public class DateTimePicker
: Control
{
46 public static readonly DateTime MaxDateTime
;
47 public static readonly DateTime MinDateTime
;
50 // --- Protected Fields
52 protected static readonly Color DefaultMonthBackColor
;
53 protected static readonly Color DefaultTitleBackColor
;
54 protected static readonly Color DefaultTitleForeColor
;
55 protected static readonly Color DefaultTrailingForeColor
;
60 private Font calendarFont
;
61 private Color calendarForeColor
;
62 private Color calendarMonthBackground
;
63 private Color calendarTitleBackColor
;
64 private Color calendarTitleForeColor
;
65 private Color calendarTrailingForeColor
;
67 private string customFormat
;
68 private LeftRightAlignment dropDownAlign
;
69 private DateTimePickerFormat format
;
70 private DateTime maxDate
;
71 private DateTime minDate
;
72 private int preferredHeight
;
73 private bool showCheckBox
;
74 private bool showUpDown
;
78 // --- Constructors/Destructors
82 public DateTimePicker() : base()
85 calendarFont
= Control
.DefaultFont
;
86 calendarForeColor
= ForeColor
;
87 calendarMonthBackground
= DefaultMonthBackColor
;
88 calendarTitleBackColor
= DefaultTitleBackColor
;
89 calendarTitleForeColor
= DefaultTitleForeColor
;
90 calendarTrailingForeColor
= DefaultTrailingForeColor
;
93 dropDownAlign
= LeftRightAlignment
.Left
;
94 format
= DateTimePickerFormat
.Long
;
95 maxDate
= MaxDateTime
;
96 minDate
= MinDateTime
;
103 static DateTimePicker()
105 MaxDateTime
= new DateTime(9998,12,31,23,59,59);
106 MinDateTime
= new DateTime(1753,1,1,0,0,0);
107 // As usual, the MS docs aren't very helpful...
108 // I'm guessing these are all the right colors... not sure though
109 // I'll check on Windows when I'm in a more masochistic mood ;)
110 DefaultMonthBackColor
= System
.Drawing
.SystemColors
.Window
;
111 DefaultTitleBackColor
= System
.Drawing
.SystemColors
.ActiveCaption
;
112 DefaultTitleForeColor
= System
.Drawing
.SystemColors
.ActiveCaptionText
;
113 DefaultTrailingForeColor
= System
.Drawing
.SystemColors
.WindowText
;
117 // --- Public Methods
119 public override string ToString(){
120 return GetType().FullName
.ToString() + ", Value: " + Value
.ToString( );
124 // --- Protected Methods
127 protected override AccessibleObject
CreateAccessibilityInstance()
130 return base.CreateAccessibilityInstance();;
134 protected override void CreateHandle()
136 initCommonControlsLibrary();
141 protected override void DestroyHandle()
144 base.DestroyHandle();
148 protected override void Dispose(bool disposing
){
149 base.Dispose(disposing
);
153 protected override bool IsInputKey(Keys keyData
)
156 return base.IsInputKey(keyData
);
159 protected virtual void OnCloseUp(EventArgs eventargs
) {
160 if ( CloseUp
!= null )
161 CloseUp( this, eventargs
);
164 protected virtual void OnDropDown(EventArgs eventargs
) {
165 if ( DropDown
!= null )
166 DropDown( this, eventargs
);
170 protected override void OnFontChanged(EventArgs e
)
173 //if (FontChanged != null) {
174 // FontChanged(this, e);
178 protected virtual void OnFormatChanged(EventArgs e
) {
179 if (FormatChanged
!= null)
180 FormatChanged(this, e
);
184 protected override void OnSystemColorsChanged(EventArgs e
)
186 base.OnSystemColorsChanged( e
);
189 //FIXME: should be inherated
190 protected override void OnHandleCreated(EventArgs e
) {
191 base.OnHandleCreated(e
);
194 setCalendarColors( );
199 protected virtual void OnValueChanged(EventArgs eventargs
) {
200 if (ValueChanged
!= null)
201 ValueChanged(this, eventargs
);
205 protected override void SetBoundsCore(int x
, int y
, int width
, int height
, BoundsSpecified specified
)
208 base.SetBoundsCore(x
, y
, width
, height
, specified
);
212 protected override void WndProc(ref Message m
)
214 switch ((Msg
) m
.Msg
) {
216 if ( m
.LParam
!= IntPtr
.Zero
)
217 handleNotification ( ref m
);
219 CallControlWndProc(ref m
);
222 CallControlWndProc(ref m
);
230 public event EventHandler CloseUp
;
231 public event EventHandler DropDown
;
232 public event EventHandler FormatChanged
;
233 public event EventHandler ValueChanged
;
236 // --- Public Properties
238 [EditorBrowsable (EditorBrowsableState
.Never
)]
239 public override Color BackColor
{
240 get { return base.BackColor; }
241 set { base.BackColor = value; }
244 [EditorBrowsable (EditorBrowsableState
.Never
)]
245 public override Image BackgroundImage
{
246 get { return base.BackgroundImage; }
247 set { base.BackgroundImage = value;}
250 public Font CalendarFont
{
251 get { return calendarFont; }
253 calendarFont
= value;
258 public Color CalendarForeColor
{
259 get { return calendarForeColor; }
261 if ( calendarForeColor
!= value ) {
262 calendarForeColor
= value;
263 setCalendarColor( (int) MonthCalColors
.MCSC_TEXT
, value );
268 public Color CalendarMonthBackground
{
269 get { return calendarMonthBackground; }
271 if ( calendarMonthBackground
!= value ) {
272 calendarMonthBackground
= value;
273 setCalendarColor( (int) MonthCalColors
.MCSC_MONTHBK
, value );
278 public Color CalendarTitleBackColor
{
279 get { return calendarTitleBackColor; }
281 if ( calendarTitleBackColor
!= value ) {
282 calendarTitleBackColor
= value;
283 setCalendarColor( (int) MonthCalColors
.MCSC_TITLEBK
, value );
288 public Color CalendarTitleForeColor
{
289 get { return calendarTitleForeColor; }
291 if ( calendarTitleForeColor
!= value ) {
292 calendarTitleForeColor
= value;
293 setCalendarColor( (int) MonthCalColors
.MCSC_TITLETEXT
, value );
298 public Color CalendarTrailingForeColor
{
299 get { return calendarTrailingForeColor; }
301 if ( calendarTrailingForeColor
!= value ) {
302 calendarTrailingForeColor
= value;
303 setCalendarColor( (int) MonthCalColors
.MCSC_TRAILINGTEXT
, value );
308 public bool Checked
{
311 getControlValue ( false ); // don't actually update the Value property
321 public string CustomFormat
{
322 get { return customFormat; }
324 customFormat
= value;
329 public LeftRightAlignment DropDownAlign
331 get { return dropDownAlign; }
333 if ( !Enum
.IsDefined ( typeof(LeftRightAlignment
), value ) )
334 throw new InvalidEnumArgumentException( "DropDownAlign",
336 typeof(LeftRightAlignment
));
338 if ( dropDownAlign
!= value ) {
339 dropDownAlign
= value;
340 if ( IsHandleCreated
)
346 [EditorBrowsable (EditorBrowsableState
.Never
)]
347 public override Color ForeColor
{
348 get { return base.ForeColor; }
349 set { base.ForeColor = value; }
352 public DateTimePickerFormat Format
{
353 get { return format; }
355 if ( !Enum
.IsDefined ( typeof(DateTimePickerFormat
), value ) )
356 throw new InvalidEnumArgumentException( "Format",
358 typeof(DateTimePickerFormat
));
360 if ( format
!= value ) {
361 int StyleToRemove
= formatStyle ( format
);
363 if ( IsHandleCreated
)
364 Win32
.UpdateWindowStyle ( Handle
, StyleToRemove
, formatStyle ( format
) );
365 OnFormatChanged( EventArgs
.Empty
);
370 public DateTime MaxDate
{
371 get { return maxDate; }
373 if ( value == maxDate
)
376 if ( value < MinDate
)
377 throw new ArgumentException (
378 string.Format ("'{0}' is not a valid value for 'MaxDate'. 'MaxDate' must be greater than or equal to MinDate", value ) );
380 if ( value > MaxDateTime
)
381 throw new ArgumentException (
382 string.Format ("DateTimePicker does not support dates after {0}.", MaxDateTime
) );
389 public DateTime MinDate
{
390 get { return minDate; }
392 if ( value == minDate
)
395 if ( value >= MaxDate
)
396 throw new ArgumentException (
397 string.Format ("'{0}' is not a valid value for 'MinDate'. 'MinDate' must be less than MaxDate.", value ) );
399 if ( value < MinDateTime
)
400 throw new ArgumentException (
401 string.Format ("DateTimePicker does not support dates before {0}.", MinDateTime
) );
409 public int PreferredHeight
{
415 public bool ShowCheckBox
{
416 get { return showCheckBox; }
418 if ( showCheckBox
!= value ) {
419 showCheckBox
= value;
420 if ( IsHandleCreated
)
426 public bool ShowUpDown
{
427 get { return showUpDown; }
429 if ( showUpDown
!= value ) {
431 if ( IsHandleCreated
)
437 [EditorBrowsable (EditorBrowsableState
.Never
)]
438 public override string Text
{
439 get { return base.Text; }
440 set { base.Text = value;}
444 public DateTime Value
{
446 getControlValue( true );
450 if ( val
!= value ) {
451 val
= value; // do we need to check that the value is in the range ?
453 OnValueChanged ( EventArgs
.Empty
);
459 // --- Protected Properties
462 protected override CreateParams CreateParams
{
464 CreateParams createParams
= base.CreateParams
;
466 createParams
.ClassName
= "SysDateTimePick32";
468 createParams
.Style
= (int) (
469 WindowStyles
.WS_CHILDWINDOW
|
470 WindowStyles
.WS_VISIBLE
|
471 WindowStyles
.WS_CLIPCHILDREN
|
472 WindowStyles
.WS_CLIPSIBLINGS
);
475 createParams
.Style
|= (int) DateTimePickerControlStyles
.DTS_UPDOWN
;
478 createParams
.Style
|= (int) DateTimePickerControlStyles
.DTS_SHOWNONE
;
480 if ( DropDownAlign
== LeftRightAlignment
.Right
)
481 createParams
.Style
|= (int) DateTimePickerControlStyles
.DTS_RIGHTALIGN
;
483 createParams
.Style
|= formatStyle ( Format
);
489 protected override Size DefaultSize
{
490 get{ return new System.Drawing.Size(200,20); }
493 private void initCommonControlsLibrary ( ) {
494 if ( !RecreatingHandle
) {
495 INITCOMMONCONTROLSEX initEx
= new INITCOMMONCONTROLSEX();
496 initEx
.dwICC
= CommonControlInitFlags
.ICC_DATE_CLASSES
;
497 Win32
.InitCommonControlsEx(initEx
);
501 private SYSTIME
toSysTime ( DateTime val
) {
502 SYSTIME systime
= new SYSTIME() ;
503 systime
.wDay
= (ushort)val
.Day
;
504 systime
.wHour
= (ushort)val
.Hour
;
505 systime
.wMilliseconds
= (ushort)val
.Millisecond
;
506 systime
.wMinute
= (ushort)val
.Minute
;
507 systime
.wMonth
= (ushort)val
.Month
;
508 systime
.wSecond
= (ushort)val
.Second
;
509 systime
.wYear
= (ushort)val
.Year
;
513 private DateTime
toDateTime ( ref SYSTIME val
) {
514 return new DateTime( val
.wYear
, val
.wMonth
, val
.wDay
,
515 val
.wHour
, val
.wMinute
, val
.wSecond
,
519 private void setControlValue ( ) {
520 if ( IsHandleCreated
) {
521 SYSTIME systime
= toSysTime ( val
) ;
523 IntPtr ptr
= Marshal
.AllocHGlobal ( Marshal
.SizeOf ( systime
) );
524 Marshal
.StructureToPtr( systime
, ptr
, false );
525 Win32
.SendMessage ( Handle
, (int)DateTimePickerMessages
.DTM_SETSYSTEMTIME
,
526 (int)DateTimePickerFlags
.GDT_VALID
, ptr
);
527 Marshal
.FreeHGlobal ( ptr
);
531 private void setCheckState ( ) {
535 if ( IsHandleCreated
) {
536 Win32
.SendMessage ( Handle
, (int)DateTimePickerMessages
.DTM_SETSYSTEMTIME
,
537 (int)DateTimePickerFlags
.GDT_NONE
, 0 );
542 private void getControlValue ( bool updateProp
) {
543 if ( IsHandleCreated
) {
544 SYSTIME systime
= new SYSTIME();
545 IntPtr ptr
= Marshal
.AllocHGlobal ( Marshal
.SizeOf ( systime
) );
546 Marshal
.StructureToPtr( systime
, ptr
, false );
547 int res
= Win32
.SendMessage ( Handle
, (int)DateTimePickerMessages
.DTM_GETSYSTEMTIME
,
549 if ( res
== (int)DateTimePickerFlags
.GDT_VALID
) {
550 systime
= Marshal
.PtrToStructure ( ptr
, systime
.GetType ( ) ) as SYSTIME
;
551 DateTime newValue
= toDateTime ( ref systime
);
553 CHecked
= !( newValue
== val
|| newValue
== DateTime
.Now
);
560 Marshal
.FreeHGlobal ( ptr
);
564 private void setControlRange ( ) {
565 if ( IsHandleCreated
) {
566 SYSTIME
[] range
= { toSysTime ( MinDate ), toSysTime ( MaxDate ) }
;
567 IntPtr buffer
= Marshal
.AllocHGlobal ( Marshal
.SizeOf( range
[0] ) * 2 );
568 IntPtr current
= buffer
;
569 Marshal
.StructureToPtr ( range
[0], current
, false );
570 current
= (IntPtr
)( current
.ToInt32() + Marshal
.SizeOf( range
[0] ) );
571 Marshal
.StructureToPtr ( range
[1], current
, false );
572 Win32
.SendMessage( Handle
, (int)DateTimePickerMessages
.DTM_SETRANGE
,
573 (int)( DateTimePickerFlags
.GDTR_MIN
| DateTimePickerFlags
.GDTR_MAX
),
575 Marshal
.FreeHGlobal ( buffer
);
579 private void setCalendarColor ( int ColorFlag
, Color clr
) {
580 if ( IsHandleCreated
)
581 Win32
.SendMessage ( Handle
, (int)DateTimePickerMessages
.DTM_SETMCCOLOR
, ColorFlag
, Win32
.RGB(clr
) );
584 private void setCalendarColors ( ) {
585 if ( calendarForeColor
!= ForeColor
)
586 setCalendarColor( (int) MonthCalColors
.MCSC_TEXT
, calendarForeColor
);
587 if ( calendarMonthBackground
!= DefaultMonthBackColor
)
588 setCalendarColor( (int) MonthCalColors
.MCSC_MONTHBK
, calendarMonthBackground
);
589 if ( calendarTitleBackColor
!= DefaultTitleBackColor
)
590 setCalendarColor( (int) MonthCalColors
.MCSC_TITLEBK
, calendarTitleBackColor
);
591 if ( calendarTitleForeColor
!= DefaultTitleForeColor
)
592 setCalendarColor( (int) MonthCalColors
.MCSC_TITLETEXT
, calendarTitleForeColor
);
593 if ( calendarTrailingForeColor
!= DefaultTrailingForeColor
)
594 setCalendarColor( (int) MonthCalColors
.MCSC_TRAILINGTEXT
, calendarTrailingForeColor
);
597 private int formatStyle ( DateTimePickerFormat format
) {
601 case DateTimePickerFormat
.Long
:
602 style
= (int)DateTimePickerControlStyles
.DTS_LONGDATEFORMAT
;
604 case DateTimePickerFormat
.Short
:
605 style
= (int)DateTimePickerControlStyles
.DTS_SHORTDATEFORMAT
;
607 case DateTimePickerFormat
.Time
:
608 style
= (int)DateTimePickerControlStyles
.DTS_TIMEFORMAT
;
614 private void setCustomFormat ( ) {
615 if ( Format
== DateTimePickerFormat
.Custom
&& IsHandleCreated
)
616 Win32
.SendMessage ( Handle
, (int)DateTimePickerMessages
.DTM_SETFORMATA
, 0, CustomFormat
);
619 private void setCalendarFont ( ) {
620 // This code will not work because Font.Equals is not implemented
622 if ( IsHandleCreated && !CalendarFont.Equals( Control.DefaultFont ) )
623 Win32.SendMessage ( Handle, (int)DateTimePickerMessages.DTM_SETMCFONT,
624 CalendarFont.ToHfont().ToInt32(), 0 );
628 private void handleNotification ( ref Message m
) {
629 NMHDR nmhdr
= (NMHDR
)Marshal
.PtrToStructure ( m
.LParam
, typeof ( NMHDR
) );
631 m
.Result
= IntPtr
.Zero
;
633 switch ( nmhdr
.code
) {
634 case (int)DateTimePickerNotifications
.DTN_CLOSEUP
:
635 OnCloseUp ( EventArgs
.Empty
);
637 case (int)DateTimePickerNotifications
.DTN_DROPDOWN
:
638 OnDropDown ( EventArgs
.Empty
);
640 case (int)DateTimePickerNotifications
.DTN_DATETIMECHANGE
:
641 getControlValue ( true );
642 OnValueChanged ( EventArgs
.Empty
);
645 CallControlWndProc ( ref m
);