bug using Application.EnableVisualStyles() with datetimepicker control

G

Guy

I have extended the datetimepicker control to incorporate
a ReadOnly property.
I have used the new keyword to implement my own version
of the value property, so that if readonly == true then
it will not set the value of the control and will leave
the checked status of the checkbox to false when a user
selects a new date.

this works fine when using the control on a win2k machine
but if we use it on a win XP box and call
Application.EnableVisualStyles() then it seems to ignore
my code and check the checkbox and set the value. this is
extremely buggy behaviour! and also the value property
gets called twice (only once on a win2k box).

i have also noticed behaviour changes in the
label.textalignment property when using XP Visual styles
aswell. Below is my implementation of the extended
datetimepicker and also the new data type
(OptionalDateTime) that is used for the value property...

#####LockableDateTimePicker Source###########

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using HCS.DataTypes;

namespace HCS.Generic.UI.Controls
{
/// <summary>
/// LockableDateTimePicker is for selecting
dates. It manipulates the OptionalDateTime
/// class to allow null dates to be handled.
/// </summary>
public class LockableDateTimePicker :
DateTimePicker
{
#region Clean Up Code

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool
disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose
();
}
}
base.Dispose( disposing );
}

#endregion

#region Component Designer generated code
/// <summary>
/// Required method for Designer support -
do not modify
/// the contents of this method with the
code editor.
/// </summary>
private void InitializeComponent()
{
components = new
System.ComponentModel.Container();
}
#endregion

#region Fields

private System.ComponentModel.Container
components = null;
private bool mReadOnly;
private DateTime mDateTime;
private Color mBackColor;
private Color mLockedColor;
private bool mChecked;

#endregion

#region Events

public event OnReadOnlyChangedDelegate
OnReadOnlyChanged;

#endregion

#region EventArgs and Delegates

public class OnReadOnlyChangedEventArgs :
EventArgs
{
private bool mReadOnly;

public OnReadOnlyChangedEventArgs
(bool ReadOnly)
{
mReadOnly = ReadOnly;
}
public bool ReadOnly
{
get
{
return mReadOnly;
}
}
}
public delegate void
OnReadOnlyChangedDelegate(object sender,
OnReadOnlyChangedEventArgs e);

#endregion

#region Constructor

public LockableDateTimePicker()
{
// This call is required by the
Windows.Forms Form Designer.
InitializeComponent();

mBackColor =
base.CalendarMonthBackground;
mLockedColor =
base.CalendarMonthBackground;

//Set defaults for this control
base.Format =
DateTimePickerFormat.Short;

//Make sure that our date backup
is populated
mDateTime = base.Value;
mChecked = base.Checked;
}

#endregion

#region Properties

[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public bool ReadOnly
{
get
{
return mReadOnly;
}
set
{
if(value)
{

base.CalendarMonthBackground = mLockedColor;
}
else
{

base.CalendarMonthBackground = mBackColor;
}

mReadOnly = value;
if(OnReadOnlyChanged !=
null)
{
OnReadOnlyChanged
(this, new OnReadOnlyChangedEventArgs(value));
}
}
}

[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public Color LockedColor
{
get
{
return mLockedColor;
}
set
{
mLockedColor = value;
}
}

#endregion

#region Public Overridden Properties
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
mBackColor = value;
if(!mReadOnly)
{
base.BackColor =
value;
}
}
}
public new OptionalDateTime Value
{
set
{
if(value.GetValue() == "")
{
base.Checked =
false;
}
else
{
base.Value =
DateTime.Parse(value.GetValue());
}

}
get
{
if(base.Checked)
{
return new
OptionalDateTime(base.Value);
}
else
{
return new
OptionalDateTime();
}
}
}
#endregion

#region Public Overridden Events

protected override void OnValueChanged
(EventArgs eventargs)
{
base.OnValueChanged (eventargs);

if(mReadOnly)
{
//We need to set the
value of the control back to
//the stored value, since
it is read only
if(base.Value !=
mDateTime)
{
base.Value =
mDateTime;
}
if(base.Checked !=
mChecked)
{
base.Checked =
mChecked;
}
}
else
{
//Store the value for
when it's read only
mDateTime = base.Value;
mChecked = base.Checked;
}
}

#endregion

#region Public Methods
public void Initialise(OptionalDateTime
Value)
{
//Temporarily set the control to
not ReadOnly.
bool mTempReadOnly = mReadOnly;
if(mReadOnly)
{
mReadOnly = false;
}

if(Value.GetValue() == "")
{
base.Checked = false;
mChecked = false;
}
else
{
base.Value =
DateTime.Parse(Value.GetValue());
base.Checked = true;
mDateTime = base.Value;
mChecked = true;
}

//Make sure the ReadOnly value is
returned to normal
mReadOnly = mTempReadOnly;
}
public void Initialise(DateTime Value)
{
Initialise(new OptionalDateTime
(Value));
}
public void Initialise()
{
Initialise(new OptionalDateTime
());
}
#endregion
}
}

##############OptionalDateTime Source##########

[Serializable()]
public class OptionalDateTime
{
#region Enum
/// <summary>
/// Formats available - extend as
required, but remember to update <see cref="GetValue"/>.
/// </summary>
public enum enumDateTimeFormat
{
/// <summary>
/// LongDateFormat
/// </summary>
LongDateFormat,
/// <summary>
/// LongTimeFormat
/// </summary>
LongTimeFormat,
/// <summary>
/// ShortDateFormat
/// </summary>
ShortDateFormat,
/// <summary>
/// ShortTimeFormat
/// </summary>
ShortTimeFormat
}
#endregion

#region Fields
private DateTime mDate;
private bool mIsNull;
#endregion

#region Constructor
/// <summary>
/// Constructor - initialises a null
OptionalDateTime
/// </summary>
public OptionalDateTime()
{
mIsNull = true;
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a string.
/// If the string is not a valid
DateTime, the object is set to contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public OptionalDateTime(string value)
{
SetValue(value);
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a DateTime.
/// </summary>
/// <param name="value">A DateTime value
type.</param>
public OptionalDateTime(DateTime value)
{
SetValue(value);
}
#endregion

#region Public Methods
/// <summary>
/// Set the value of the object to equal
that of a DateTime.
/// </summary>
/// <param name="value">A
DateTime.</param>
public void SetValue(DateTime value)
{
mDate = value;
mIsNull = false;
}
/// <summary>
/// Set the value of the object to equal
that of a string. If the string is not a valid
/// DateTime, the object is set to
contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public void SetValue(string value)
{
if(value == null || value == "")
{
mIsNull = true;
}
else
{
try
{
mDate =
DateTime.Parse(value);
mIsNull = false;
}
catch
{
throw new
ArgumentException("The string entered cannot be converted
to a DateTime", "value");
}
}
}
/// <summary>
/// Return the value of the object as a
string with optional formatting.
/// </summary>
/// <param name="Format">The format to
return.</param>
/// <returns>A string containing the
correctly formatted date.</returns>
public string GetValue(enumDateTimeFormat
Format)
{
if(mIsNull)
{
return "";
}
else
{
switch(Format)
{
case
enumDateTimeFormat.LongDateFormat:
return
mDate.ToLongDateString();
case
enumDateTimeFormat.LongTimeFormat:
return
mDate.ToLongTimeString();
case
enumDateTimeFormat.ShortDateFormat:
return
mDate.ToShortDateString();
case
enumDateTimeFormat.ShortTimeFormat:
return
mDate.ToShortTimeString();
default:
throw new
UnhandledDateFormatException(Format);
}
}
}
/// <summary>
/// Return the value of the object as a
ShortDateString.
/// </summary>
/// <returns></returns>
public string GetValue()
{
return GetValue
(enumDateTimeFormat.ShortDateFormat);
}
#endregion

#region Public Override Methods
/// <summary>
/// Passes a string containing the date
in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
/// </summary>
/// <returns>The date returned. Passes an
empty string for blank (null) dates.</returns>
public override string ToString()
{
return GetValue();
}
#endregion

#region Properties
/// <summary>
/// Returns the date of the
OptionalDateTime as a DateTime type. Raises the
/// <see
cref="OptionalDateTimeIsNullException"/> if the
OptionalDateTime is
/// blank (null). Check the <see
cref="IsNull"/> property before calling this
/// method to avoid the exception.
/// </summary>
public DateTime GetDateTime
{
get
{
if(mIsNull)
{
throw new
OptionalDateTimeIsNullException();
}
return mDate;
}
}
/// <summary>
/// Gets a boolean value indicating
whether the OptionalDateTime is blank (null).
/// </summary>
public bool IsNull
{
get
{
return mIsNull;
}
}
#endregion
}

thanks in advance
 
J

Jeffrey Tan[MSFT]

Hi Guy,

It is an already known issue.
I will do some research on this to find some workaround for you.
Thanks for you understanding.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "Guy" <[email protected]>
| Sender: "Guy" <[email protected]>
| Subject: bug using Application.EnableVisualStyles() with datetimepicker
control
| Date: Fri, 24 Oct 2003 03:56:32 -0700
| Lines: 540
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:193774
| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| I have extended the datetimepicker control to incorporate
| a ReadOnly property.
| I have used the new keyword to implement my own version
| of the value property, so that if readonly == true then
| it will not set the value of the control and will leave
| the checked status of the checkbox to false when a user
| selects a new date.
|
| this works fine when using the control on a win2k machine
| but if we use it on a win XP box and call
| Application.EnableVisualStyles() then it seems to ignore
| my code and check the checkbox and set the value. this is
| extremely buggy behaviour! and also the value property
| gets called twice (only once on a win2k box).
|
| i have also noticed behaviour changes in the
| label.textalignment property when using XP Visual styles
| aswell. Below is my implementation of the extended
| datetimepicker and also the new data type
| (OptionalDateTime) that is used for the value property...
|
| #####LockableDateTimePicker Source###########
|
| using System;
| using System.Collections;
| using System.ComponentModel;
| using System.Drawing;
| using System.Data;
| using System.Windows.Forms;
| using HCS.DataTypes;
|
| namespace HCS.Generic.UI.Controls
| {
| /// <summary>
| /// LockableDateTimePicker is for selecting
| dates. It manipulates the OptionalDateTime
| /// class to allow null dates to be handled.
| /// </summary>
| public class LockableDateTimePicker :
| DateTimePicker
| {
| #region Clean Up Code
|
| /// <summary>
| /// Clean up any resources being used.
| /// </summary>
| protected override void Dispose( bool
| disposing )
| {
| if( disposing )
| {
| if(components != null)
| {
| components.Dispose
| ();
| }
| }
| base.Dispose( disposing );
| }
|
| #endregion
|
| #region Component Designer generated code
| /// <summary>
| /// Required method for Designer support -
| do not modify
| /// the contents of this method with the
| code editor.
| /// </summary>
| private void InitializeComponent()
| {
| components = new
| System.ComponentModel.Container();
| }
| #endregion
|
| #region Fields
|
| private System.ComponentModel.Container
| components = null;
| private bool mReadOnly;
| private DateTime mDateTime;
| private Color mBackColor;
| private Color mLockedColor;
| private bool mChecked;
|
| #endregion
|
| #region Events
|
| public event OnReadOnlyChangedDelegate
| OnReadOnlyChanged;
|
| #endregion
|
| #region EventArgs and Delegates
|
| public class OnReadOnlyChangedEventArgs :
| EventArgs
| {
| private bool mReadOnly;
|
| public OnReadOnlyChangedEventArgs
| (bool ReadOnly)
| {
| mReadOnly = ReadOnly;
| }
| public bool ReadOnly
| {
| get
| {
| return mReadOnly;
| }
| }
| }
| public delegate void
| OnReadOnlyChangedDelegate(object sender,
| OnReadOnlyChangedEventArgs e);
|
| #endregion
|
| #region Constructor
|
| public LockableDateTimePicker()
| {
| // This call is required by the
| Windows.Forms Form Designer.
| InitializeComponent();
|
| mBackColor =
| base.CalendarMonthBackground;
| mLockedColor =
| base.CalendarMonthBackground;
|
| //Set defaults for this control
| base.Format =
| DateTimePickerFormat.Short;
|
| //Make sure that our date backup
| is populated
| mDateTime = base.Value;
| mChecked = base.Checked;
| }
|
| #endregion
|
| #region Properties
|
| [DesignerSerializationVisibility
| (DesignerSerializationVisibility.Visible)]
| public bool ReadOnly
| {
| get
| {
| return mReadOnly;
| }
| set
| {
| if(value)
| {
|
| base.CalendarMonthBackground = mLockedColor;
| }
| else
| {
|
| base.CalendarMonthBackground = mBackColor;
| }
|
| mReadOnly = value;
| if(OnReadOnlyChanged !=
| null)
| {
| OnReadOnlyChanged
| (this, new OnReadOnlyChangedEventArgs(value));
| }
| }
| }
|
| [DesignerSerializationVisibility
| (DesignerSerializationVisibility.Visible)]
| public Color LockedColor
| {
| get
| {
| return mLockedColor;
| }
| set
| {
| mLockedColor = value;
| }
| }
|
| #endregion
|
| #region Public Overridden Properties
| public override Color BackColor
| {
| get
| {
| return base.BackColor;
| }
| set
| {
| mBackColor = value;
| if(!mReadOnly)
| {
| base.BackColor =
| value;
| }
| }
| }
| public new OptionalDateTime Value
| {
| set
| {
| if(value.GetValue() == "")
| {
| base.Checked =
| false;
| }
| else
| {
| base.Value =
| DateTime.Parse(value.GetValue());
| }
|
| }
| get
| {
| if(base.Checked)
| {
| return new
| OptionalDateTime(base.Value);
| }
| else
| {
| return new
| OptionalDateTime();
| }
| }
| }
| #endregion
|
| #region Public Overridden Events
|
| protected override void OnValueChanged
| (EventArgs eventargs)
| {
| base.OnValueChanged (eventargs);
|
| if(mReadOnly)
| {
| //We need to set the
| value of the control back to
| //the stored value, since
| it is read only
| if(base.Value !=
| mDateTime)
| {
| base.Value =
| mDateTime;
| }
| if(base.Checked !=
| mChecked)
| {
| base.Checked =
| mChecked;
| }
| }
| else
| {
| //Store the value for
| when it's read only
| mDateTime = base.Value;
| mChecked = base.Checked;
| }
| }
|
| #endregion
|
| #region Public Methods
| public void Initialise(OptionalDateTime
| Value)
| {
| //Temporarily set the control to
| not ReadOnly.
| bool mTempReadOnly = mReadOnly;
| if(mReadOnly)
| {
| mReadOnly = false;
| }
|
| if(Value.GetValue() == "")
| {
| base.Checked = false;
| mChecked = false;
| }
| else
| {
| base.Value =
| DateTime.Parse(Value.GetValue());
| base.Checked = true;
| mDateTime = base.Value;
| mChecked = true;
| }
|
| //Make sure the ReadOnly value is
| returned to normal
| mReadOnly = mTempReadOnly;
| }
| public void Initialise(DateTime Value)
| {
| Initialise(new OptionalDateTime
| (Value));
| }
| public void Initialise()
| {
| Initialise(new OptionalDateTime
| ());
| }
| #endregion
| }
| }
|
| ##############OptionalDateTime Source##########
|
| [Serializable()]
| public class OptionalDateTime
| {
| #region Enum
| /// <summary>
| /// Formats available - extend as
| required, but remember to update <see cref="GetValue"/>.
| /// </summary>
| public enum enumDateTimeFormat
| {
| /// <summary>
| /// LongDateFormat
| /// </summary>
| LongDateFormat,
| /// <summary>
| /// LongTimeFormat
| /// </summary>
| LongTimeFormat,
| /// <summary>
| /// ShortDateFormat
| /// </summary>
| ShortDateFormat,
| /// <summary>
| /// ShortTimeFormat
| /// </summary>
| ShortTimeFormat
| }
| #endregion
|
| #region Fields
| private DateTime mDate;
| private bool mIsNull;
| #endregion
|
| #region Constructor
| /// <summary>
| /// Constructor - initialises a null
| OptionalDateTime
| /// </summary>
| public OptionalDateTime()
| {
| mIsNull = true;
| }
| /// <summary>
| /// Constructor - initialise an
| OptionalDateTime to contain the value of a string.
| /// If the string is not a valid
| DateTime, the object is set to contain a null date.
| /// </summary>
| /// <param name="value">A string
| representing a valid date.</param>
| public OptionalDateTime(string value)
| {
| SetValue(value);
| }
| /// <summary>
| /// Constructor - initialise an
| OptionalDateTime to contain the value of a DateTime.
| /// </summary>
| /// <param name="value">A DateTime value
| type.</param>
| public OptionalDateTime(DateTime value)
| {
| SetValue(value);
| }
| #endregion
|
| #region Public Methods
| /// <summary>
| /// Set the value of the object to equal
| that of a DateTime.
| /// </summary>
| /// <param name="value">A
| DateTime.</param>
| public void SetValue(DateTime value)
| {
| mDate = value;
| mIsNull = false;
| }
| /// <summary>
| /// Set the value of the object to equal
| that of a string. If the string is not a valid
| /// DateTime, the object is set to
| contain a null date.
| /// </summary>
| /// <param name="value">A string
| representing a valid date.</param>
| public void SetValue(string value)
| {
| if(value == null || value == "")
| {
| mIsNull = true;
| }
| else
| {
| try
| {
| mDate =
| DateTime.Parse(value);
| mIsNull = false;
| }
| catch
| {
| throw new
| ArgumentException("The string entered cannot be converted
| to a DateTime", "value");
| }
| }
| }
| /// <summary>
| /// Return the value of the object as a
| string with optional formatting.
| /// </summary>
| /// <param name="Format">The format to
| return.</param>
| /// <returns>A string containing the
| correctly formatted date.</returns>
| public string GetValue(enumDateTimeFormat
| Format)
| {
| if(mIsNull)
| {
| return "";
| }
| else
| {
| switch(Format)
| {
| case
| enumDateTimeFormat.LongDateFormat:
| return
| mDate.ToLongDateString();
| case
| enumDateTimeFormat.LongTimeFormat:
| return
| mDate.ToLongTimeString();
| case
| enumDateTimeFormat.ShortDateFormat:
| return
| mDate.ToShortDateString();
| case
| enumDateTimeFormat.ShortTimeFormat:
| return
| mDate.ToShortTimeString();
| default:
| throw new
| UnhandledDateFormatException(Format);
| }
| }
| }
| /// <summary>
| /// Return the value of the object as a
| ShortDateString.
| /// </summary>
| /// <returns></returns>
| public string GetValue()
| {
| return GetValue
| (enumDateTimeFormat.ShortDateFormat);
| }
| #endregion
|
| #region Public Override Methods
| /// <summary>
| /// Passes a string containing the date
| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| /// </summary>
| /// <returns>The date returned. Passes an
| empty string for blank (null) dates.</returns>
| public override string ToString()
| {
| return GetValue();
| }
| #endregion
|
| #region Properties
| /// <summary>
| /// Returns the date of the
| OptionalDateTime as a DateTime type. Raises the
| /// <see
| cref="OptionalDateTimeIsNullException"/> if the
| OptionalDateTime is
| /// blank (null). Check the <see
| cref="IsNull"/> property before calling this
| /// method to avoid the exception.
| /// </summary>
| public DateTime GetDateTime
| {
| get
| {
| if(mIsNull)
| {
| throw new
| OptionalDateTimeIsNullException();
| }
| return mDate;
| }
| }
| /// <summary>
| /// Gets a boolean value indicating
| whether the OptionalDateTime is blank (null).
| /// </summary>
| public bool IsNull
| {
| get
| {
| return mIsNull;
| }
| }
| #endregion
| }
|
| thanks in advance
|
 
G

guy

Ok Jeffrey, ill wait for your reply


-----Original Message-----

Hi Guy,

It is an already known issue.
I will do some research on this to find some workaround for you.
Thanks for you understanding.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "Guy" <[email protected]>
| Sender: "Guy" <[email protected]>
| Subject: bug using Application.EnableVisualStyles() with datetimepicker
control
| Date: Fri, 24 Oct 2003 03:56:32 -0700
| Lines: 540
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:193774
| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| I have extended the datetimepicker control to incorporate
| a ReadOnly property.
| I have used the new keyword to implement my own version
| of the value property, so that if readonly == true then
| it will not set the value of the control and will leave
| the checked status of the checkbox to false when a user
| selects a new date.
|
| this works fine when using the control on a win2k machine
| but if we use it on a win XP box and call
| Application.EnableVisualStyles() then it seems to ignore
| my code and check the checkbox and set the value. this is
| extremely buggy behaviour! and also the value property
| gets called twice (only once on a win2k box).
|
| i have also noticed behaviour changes in the
| label.textalignment property when using XP Visual styles
| aswell. Below is my implementation of the extended
| datetimepicker and also the new data type
| (OptionalDateTime) that is used for the value property...
|
| #####LockableDateTimePicker Source###########
|
| using System;
| using System.Collections;
| using System.ComponentModel;
| using System.Drawing;
| using System.Data;
| using System.Windows.Forms;
| using HCS.DataTypes;
|
| namespace HCS.Generic.UI.Controls
| {
| /// <summary>
| /// LockableDateTimePicker is for selecting
| dates. It manipulates the OptionalDateTime
| /// class to allow null dates to be handled.
| /// </summary>
| public class LockableDateTimePicker :
| DateTimePicker
| {
| #region Clean Up Code
|
| /// <summary>
| /// Clean up any resources being used.
| /// </summary>
| protected override void Dispose( bool
| disposing )
| {
| if( disposing )
| {
| if(components != null)
| {
| components.Dispose
| ();
| }
| }
| base.Dispose( disposing );
| }
|
| #endregion
|
| #region Component Designer generated code
| /// <summary>
| /// Required method for Designer support -
| do not modify
| /// the contents of this method with the
| code editor.
| /// </summary>
| private void InitializeComponent()
| {
| components = new
| System.ComponentModel.Container();
| }
| #endregion
|
| #region Fields
|
| private System.ComponentModel.Container
| components = null;
| private bool mReadOnly;
| private DateTime mDateTime;
| private Color mBackColor;
| private Color mLockedColor;
| private bool mChecked;
|
| #endregion
|
| #region Events
|
| public event OnReadOnlyChangedDelegate
| OnReadOnlyChanged;
|
| #endregion
|
| #region EventArgs and Delegates
|
| public class OnReadOnlyChangedEventArgs :
| EventArgs
| {
| private bool mReadOnly;
|
| public OnReadOnlyChangedEventArgs
| (bool ReadOnly)
| {
| mReadOnly = ReadOnly;
| }
| public bool ReadOnly
| {
| get
| {
| return mReadOnly;
| }
| }
| }
| public delegate void
| OnReadOnlyChangedDelegate(object sender,
| OnReadOnlyChangedEventArgs e);
|
| #endregion
|
| #region Constructor
|
| public LockableDateTimePicker()
| {
| // This call is required by the
| Windows.Forms Form Designer.
| InitializeComponent();
|
| mBackColor =
| base.CalendarMonthBackground;
| mLockedColor =
| base.CalendarMonthBackground;
|
| //Set defaults for this control
| base.Format =
| DateTimePickerFormat.Short;
|
| //Make sure that our date backup
| is populated
| mDateTime = base.Value;
| mChecked = base.Checked;
| }
|
| #endregion
|
| #region Properties
|
| [DesignerSerializationVisibility
| (DesignerSerializationVisibility.Visible)]
| public bool ReadOnly
| {
| get
| {
| return mReadOnly;
| }
| set
| {
| if(value)
| {
|
| base.CalendarMonthBackground = mLockedColor;
| }
| else
| {
|
| base.CalendarMonthBackground = mBackColor;
| }
|
| mReadOnly = value;
| if(OnReadOnlyChanged !=
| null)
| {
| OnReadOnlyChanged
| (this, new OnReadOnlyChangedEventArgs(value));
| }
| }
| }
|
| [DesignerSerializationVisibility
| (DesignerSerializationVisibility.Visible)]
| public Color LockedColor
| {
| get
| {
| return mLockedColor;
| }
| set
| {
| mLockedColor = value;
| }
| }
|
| #endregion
|
| #region Public Overridden Properties
| public override Color BackColor
| {
| get
| {
| return base.BackColor;
| }
| set
| {
| mBackColor = value;
| if(!mReadOnly)
| {
| base.BackColor =
| value;
| }
| }
| }
| public new OptionalDateTime Value
| {
| set
| {
| if(value.GetValue() == "")
| {
| base.Checked =
| false;
| }
| else
| {
| base.Value =
| DateTime.Parse(value.GetValue());
| }
|
| }
| get
| {
| if(base.Checked)
| {
| return new
| OptionalDateTime(base.Value);
| }
| else
| {
| return new
| OptionalDateTime();
| }
| }
| }
| #endregion
|
| #region Public Overridden Events
|
| protected override void OnValueChanged
| (EventArgs eventargs)
| {
| base.OnValueChanged (eventargs);
|
| if(mReadOnly)
| {
| //We need to set the
| value of the control back to
| //the stored value, since
| it is read only
| if(base.Value !=
| mDateTime)
| {
| base.Value =
| mDateTime;
| }
| if(base.Checked !=
| mChecked)
| {
| base.Checked =
| mChecked;
| }
| }
| else
| {
| //Store the value for
| when it's read only
| mDateTime = base.Value;
| mChecked = base.Checked;
| }
| }
|
| #endregion
|
| #region Public Methods
| public void Initialise(OptionalDateTime
| Value)
| {
| //Temporarily set the control to
| not ReadOnly.
| bool mTempReadOnly = mReadOnly;
| if(mReadOnly)
| {
| mReadOnly = false;
| }
|
| if(Value.GetValue() == "")
| {
| base.Checked = false;
| mChecked = false;
| }
| else
| {
| base.Value =
| DateTime.Parse(Value.GetValue());
| base.Checked = true;
| mDateTime = base.Value;
| mChecked = true;
| }
|
| //Make sure the ReadOnly value is
| returned to normal
| mReadOnly = mTempReadOnly;
| }
| public void Initialise(DateTime Value)
| {
| Initialise(new OptionalDateTime
| (Value));
| }
| public void Initialise()
| {
| Initialise(new OptionalDateTime
| ());
| }
| #endregion
| }
| }
|
| ##############OptionalDateTime Source##########
|
| [Serializable()]
| public class OptionalDateTime
| {
| #region Enum
| /// <summary>
| /// Formats available - extend as
| required, but remember to update <see cref="GetValue"/>.
| /// </summary>
| public enum enumDateTimeFormat
| {
| /// <summary>
| /// LongDateFormat
| /// </summary>
| LongDateFormat,
| /// <summary>
| /// LongTimeFormat
| /// </summary>
| LongTimeFormat,
| /// <summary>
| /// ShortDateFormat
| /// </summary>
| ShortDateFormat,
| /// <summary>
| /// ShortTimeFormat
| /// </summary>
| ShortTimeFormat
| }
| #endregion
|
| #region Fields
| private DateTime mDate;
| private bool mIsNull;
| #endregion
|
| #region Constructor
| /// <summary>
| /// Constructor - initialises a null
| OptionalDateTime
| /// </summary>
| public OptionalDateTime()
| {
| mIsNull = true;
| }
| /// <summary>
| /// Constructor - initialise an
| OptionalDateTime to contain the value of a string.
| /// If the string is not a valid
| DateTime, the object is set to contain a null date.
| /// </summary>
| /// <param name="value">A string
| representing a valid date.</param>
| public OptionalDateTime(string value)
| {
| SetValue(value);
| }
| /// <summary>
| /// Constructor - initialise an
| OptionalDateTime to contain the value of a DateTime.
| /// </summary>
| /// <param name="value">A DateTime value
| type.</param>
| public OptionalDateTime(DateTime value)
| {
| SetValue(value);
| }
| #endregion
|
| #region Public Methods
| /// <summary>
| /// Set the value of the object to equal
| that of a DateTime.
| /// </summary>
| /// <param name="value">A
| DateTime.</param>
| public void SetValue(DateTime value)
| {
| mDate = value;
| mIsNull = false;
| }
| /// <summary>
| /// Set the value of the object to equal
| that of a string. If the string is not a valid
| /// DateTime, the object is set to
| contain a null date.
| /// </summary>
| /// <param name="value">A string
| representing a valid date.</param>
| public void SetValue(string value)
| {
| if(value == null || value == "")
| {
| mIsNull = true;
| }
| else
| {
| try
| {
| mDate =
| DateTime.Parse(value);
| mIsNull = false;
| }
| catch
| {
| throw new
| ArgumentException("The string entered cannot be converted
| to a DateTime", "value");
| }
| }
| }
| /// <summary>
| /// Return the value of the object as a
| string with optional formatting.
| /// </summary>
| /// <param name="Format">The format to
| return.</param>
| /// <returns>A string containing the
| correctly formatted date.</returns>
| public string GetValue(enumDateTimeFormat
| Format)
| {
| if(mIsNull)
| {
| return "";
| }
| else
| {
| switch(Format)
| {
| case
| enumDateTimeFormat.LongDateFormat:
| return
| mDate.ToLongDateString();
| case
| enumDateTimeFormat.LongTimeFormat:
| return
| mDate.ToLongTimeString();
| case
| enumDateTimeFormat.ShortDateFormat:
| return
| mDate.ToShortDateString();
| case
| enumDateTimeFormat.ShortTimeFormat:
| return
| mDate.ToShortTimeString();
| default:
| throw new
| UnhandledDateFormatException(Format);
| }
| }
| }
| /// <summary>
| /// Return the value of the object as a
| ShortDateString.
| /// </summary>
| /// <returns></returns>
| public string GetValue()
| {
| return GetValue
| (enumDateTimeFormat.ShortDateFormat);
| }
| #endregion
|
| #region Public Override Methods
| /// <summary>
| /// Passes a string containing the date
| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| /// </summary>
| /// <returns>The date returned. Passes an
| empty string for blank (null) dates.</returns>
| public override string ToString()
| {
| return GetValue();
| }
| #endregion
|
| #region Properties
| /// <summary>
| /// Returns the date of the
| OptionalDateTime as a DateTime type. Raises the
| /// <see
| cref="OptionalDateTimeIsNullException"/> if the
| OptionalDateTime is
| /// blank (null). Check the <see
| cref="IsNull"/> property before calling this
| /// method to avoid the exception.
| /// </summary>
| public DateTime GetDateTime
| {
| get
| {
| if(mIsNull)
| {
| throw new
| OptionalDateTimeIsNullException();
| }
| return mDate;
| }
| }
| /// <summary>
| /// Gets a boolean value indicating
| whether the OptionalDateTime is blank (null).
| /// </summary>
| public bool IsNull
| {
| get
| {
| return mIsNull;
| }
| }
| #endregion
| }
|
| thanks in advance
|

.
 
J

Jeffrey Tan[MSFT]

Hi Guy,

Sorry for letting you waiting so long time.
In this time, I did a lot of research into DateTimePicker control and
wanted to find a workaround for you.
Here, I provide you 2 ways of workaround:
First: override its OnCloseUp method and reset its value to its original
value. But this is not enough, when you open the datetimepicker, you can
use keyboard arrow to navigate the selection, and the value displayed will
also change in the textbox( For the moment, we call it textbox). I think we
should not let this happen, the value should stay the same. But just reset
value in the OnValueChanged method seems work well on keyboard navigation,
but will again change the value when closing the calendar.(It seems that
the OnCloseUp abated). So I hooked into this control, and filter its
MCN_SELCHANGE notification in WM_NOTIFY message.

using System.Runtime .InteropServices ;
public bool readonlyval=false;
private DateTime oldval;

protected override void OnCloseUp(EventArgs eventargs)
{
if(readonlyval==true)
{
this.Value =oldval;
}
oldval=this.Value ;
base.OnCloseUp (eventargs);
}

private const int MCN_FIRST=-750;
private const int MCN_SELCHANGE=MCN_FIRST + 1;
private int WM_NOTIFY=0x004E;

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public int idfrom;
public int code;
}

protected override void WndProc(ref Message m)
{
if(m.Msg==WM_NOTIFY)
{
if(m.HWnd==this.Handle)
{
NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
if(nm1.code==MCN_SELCHANGE)
{
return;
}
}
}
base.WndProc (ref m);
}

I use Spy++ to find that the DateTimePicker control will receive WM_NOTIFY
message with MCN_SELCHANGE code when selection changes.
All the const value MCN_SELCHANGE, MCN_FIRST can be found in the C:\Program
Files\Microsoft Visual Studio\VC98\Include directory *.h files.

It works well on my machine. If you have any question, please feel free to
tell me.
I will reply the second way of workaround in another reply post.

Best regards
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "guy" <[email protected]>
| Sender: "guy" <[email protected]>
| References: <[email protected]>
<[email protected]>
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| Date: Tue, 28 Oct 2003 01:26:56 -0800
| Lines: 601
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:194627
| NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Ok Jeffrey, ill wait for your reply
|
|
|
| >-----Original Message-----
| >
| >Hi Guy,
| >
| >It is an already known issue.
| >I will do some research on this to find some workaround
| for you.
| >Thanks for you understanding.
| >
| >Best regards,
| >Jeffrey Tan
| >Microsoft Online Partner Support
| >Get Secure! - www.microsoft.com/security
| >This posting is provided "as is" with no warranties and
| confers no rights.
| >
| >--------------------
| >| Content-Class: urn:content-classes:message
| >| From: "Guy" <[email protected]>
| >| Sender: "Guy" <[email protected]>
| >| Subject: bug using Application.EnableVisualStyles()
| with datetimepicker
| >control
| >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| >| Lines: 540
| >| Message-ID: <[email protected]>
| >| MIME-Version: 1.0
| >| Content-Type: text/plain;
| >| charset="iso-8859-1"
| >| Content-Transfer-Encoding: 7bit
| >| X-Newsreader: Microsoft CDO for Windows 2000
| >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| >| X-MimeOLE: Produced By Microsoft MimeOLE
| V5.50.4910.0300
| >| Newsgroups: microsoft.public.dotnet.languages.csharp
| >| Path: cpmsftngxa06.phx.gbl
| >| Xref: cpmsftngxa06.phx.gbl
| microsoft.public.dotnet.languages.csharp:193774
| >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| >|
| >| I have extended the datetimepicker control to
| incorporate
| >| a ReadOnly property.
| >| I have used the new keyword to implement my own
| version
| >| of the value property, so that if readonly == true
| then
| >| it will not set the value of the control and will
| leave
| >| the checked status of the checkbox to false when a
| user
| >| selects a new date.
| >|
| >| this works fine when using the control on a win2k
| machine
| >| but if we use it on a win XP box and call
| >| Application.EnableVisualStyles() then it seems to
| ignore
| >| my code and check the checkbox and set the value. this
| is
| >| extremely buggy behaviour! and also the value property
| >| gets called twice (only once on a win2k box).
| >|
| >| i have also noticed behaviour changes in the
| >| label.textalignment property when using XP Visual
| styles
| >| aswell. Below is my implementation of the extended
| >| datetimepicker and also the new data type
| >| (OptionalDateTime) that is used for the value
| property...
| >|
| >| #####LockableDateTimePicker Source###########
| >|
| >| using System;
| >| using System.Collections;
| >| using System.ComponentModel;
| >| using System.Drawing;
| >| using System.Data;
| >| using System.Windows.Forms;
| >| using HCS.DataTypes;
| >|
| >| namespace HCS.Generic.UI.Controls
| >| {
| >| /// <summary>
| >| /// LockableDateTimePicker is for selecting
| >| dates. It manipulates the OptionalDateTime
| >| /// class to allow null dates to be handled.
| >| /// </summary>
| >| public class LockableDateTimePicker :
| >| DateTimePicker
| >| {
| >| #region Clean Up Code
| >|
| >| /// <summary>
| >| /// Clean up any resources being used.
| >| /// </summary>
| >| protected override void Dispose( bool
| >| disposing )
| >| {
| >| if( disposing )
| >| {
| >| if(components != null)
| >| {
| >| components.Dispose
| >| ();
| >| }
| >| }
| >| base.Dispose( disposing );
| >| }
| >|
| >| #endregion
| >|
| >| #region Component Designer generated code
| >| /// <summary>
| >| /// Required method for Designer support -
| >| do not modify
| >| /// the contents of this method with the
| >| code editor.
| >| /// </summary>
| >| private void InitializeComponent()
| >| {
| >| components = new
| >| System.ComponentModel.Container();
| >| }
| >| #endregion
| >|
| >| #region Fields
| >|
| >| private System.ComponentModel.Container
| >| components = null;
| >| private bool mReadOnly;
| >| private DateTime mDateTime;
| >| private Color mBackColor;
| >| private Color mLockedColor;
| >| private bool mChecked;
| >|
| >| #endregion
| >|
| >| #region Events
| >|
| >| public event OnReadOnlyChangedDelegate
| >| OnReadOnlyChanged;
| >|
| >| #endregion
| >|
| >| #region EventArgs and Delegates
| >|
| >| public class OnReadOnlyChangedEventArgs :
| >| EventArgs
| >| {
| >| private bool mReadOnly;
| >|
| >| public OnReadOnlyChangedEventArgs
| >| (bool ReadOnly)
| >| {
| >| mReadOnly = ReadOnly;
| >| }
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| }
| >| }
| >| public delegate void
| >| OnReadOnlyChangedDelegate(object sender,
| >| OnReadOnlyChangedEventArgs e);
| >|
| >| #endregion
| >|
| >| #region Constructor
| >|
| >| public LockableDateTimePicker()
| >| {
| >| // This call is required by the
| >| Windows.Forms Form Designer.
| >| InitializeComponent();
| >|
| >| mBackColor =
| >| base.CalendarMonthBackground;
| >| mLockedColor =
| >| base.CalendarMonthBackground;
| >|
| >| //Set defaults for this control
| >| base.Format =
| >| DateTimePickerFormat.Short;
| >|
| >| //Make sure that our date backup
| >| is populated
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >|
| >| #endregion
| >|
| >| #region Properties
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| set
| >| {
| >| if(value)
| >| {
| >|
| >| base.CalendarMonthBackground = mLockedColor;
| >| }
| >| else
| >| {
| >|
| >| base.CalendarMonthBackground = mBackColor;
| >| }
| >|
| >| mReadOnly = value;
| >| if(OnReadOnlyChanged !=
| >| null)
| >| {
| >| OnReadOnlyChanged
| >| (this, new OnReadOnlyChangedEventArgs(value));
| >| }
| >| }
| >| }
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public Color LockedColor
| >| {
| >| get
| >| {
| >| return mLockedColor;
| >| }
| >| set
| >| {
| >| mLockedColor = value;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Overridden Properties
| >| public override Color BackColor
| >| {
| >| get
| >| {
| >| return base.BackColor;
| >| }
| >| set
| >| {
| >| mBackColor = value;
| >| if(!mReadOnly)
| >| {
| >| base.BackColor =
| >| value;
| >| }
| >| }
| >| }
| >| public new OptionalDateTime Value
| >| {
| >| set
| >| {
| >| if(value.GetValue() == "")
| >| {
| >| base.Checked =
| >| false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(value.GetValue());
| >| }
| >|
| >| }
| >| get
| >| {
| >| if(base.Checked)
| >| {
| >| return new
| >| OptionalDateTime(base.Value);
| >| }
| >| else
| >| {
| >| return new
| >| OptionalDateTime();
| >| }
| >| }
| >| }
| >| #endregion
| >|
| >| #region Public Overridden Events
| >|
| >| protected override void OnValueChanged
| >| (EventArgs eventargs)
| >| {
| >| base.OnValueChanged (eventargs);
| >|
| >| if(mReadOnly)
| >| {
| >| //We need to set the
| >| value of the control back to
| >| //the stored value, since
| >| it is read only
| >| if(base.Value !=
| >| mDateTime)
| >| {
| >| base.Value =
| >| mDateTime;
| >| }
| >| if(base.Checked !=
| >| mChecked)
| >| {
| >| base.Checked =
| >| mChecked;
| >| }
| >| }
| >| else
| >| {
| >| //Store the value for
| >| when it's read only
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Methods
| >| public void Initialise(OptionalDateTime
| >| Value)
| >| {
| >| //Temporarily set the control to
| >| not ReadOnly.
| >| bool mTempReadOnly = mReadOnly;
| >| if(mReadOnly)
| >| {
| >| mReadOnly = false;
| >| }
| >|
| >| if(Value.GetValue() == "")
| >| {
| >| base.Checked = false;
| >| mChecked = false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(Value.GetValue());
| >| base.Checked = true;
| >| mDateTime = base.Value;
| >| mChecked = true;
| >| }
| >|
| >| //Make sure the ReadOnly value is
| >| returned to normal
| >| mReadOnly = mTempReadOnly;
| >| }
| >| public void Initialise(DateTime Value)
| >| {
| >| Initialise(new OptionalDateTime
| >| (Value));
| >| }
| >| public void Initialise()
| >| {
| >| Initialise(new OptionalDateTime
| >| ());
| >| }
| >| #endregion
| >| }
| >| }
| >|
| >| ##############OptionalDateTime Source##########
| >|
| >| [Serializable()]
| >| public class OptionalDateTime
| >| {
| >| #region Enum
| >| /// <summary>
| >| /// Formats available - extend as
| >| required, but remember to update <see
| cref="GetValue"/>.
| >| /// </summary>
| >| public enum enumDateTimeFormat
| >| {
| >| /// <summary>
| >| /// LongDateFormat
| >| /// </summary>
| >| LongDateFormat,
| >| /// <summary>
| >| /// LongTimeFormat
| >| /// </summary>
| >| LongTimeFormat,
| >| /// <summary>
| >| /// ShortDateFormat
| >| /// </summary>
| >| ShortDateFormat,
| >| /// <summary>
| >| /// ShortTimeFormat
| >| /// </summary>
| >| ShortTimeFormat
| >| }
| >| #endregion
| >|
| >| #region Fields
| >| private DateTime mDate;
| >| private bool mIsNull;
| >| #endregion
| >|
| >| #region Constructor
| >| /// <summary>
| >| /// Constructor - initialises a null
| >| OptionalDateTime
| >| /// </summary>
| >| public OptionalDateTime()
| >| {
| >| mIsNull = true;
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a string.
| >| /// If the string is not a valid
| >| DateTime, the object is set to contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public OptionalDateTime(string value)
| >| {
| >| SetValue(value);
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A DateTime value
| >| type.</param>
| >| public OptionalDateTime(DateTime value)
| >| {
| >| SetValue(value);
| >| }
| >| #endregion
| >|
| >| #region Public Methods
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A
| >| DateTime.</param>
| >| public void SetValue(DateTime value)
| >| {
| >| mDate = value;
| >| mIsNull = false;
| >| }
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a string. If the string is not a valid
| >| /// DateTime, the object is set to
| >| contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public void SetValue(string value)
| >| {
| >| if(value == null || value == "")
| >| {
| >| mIsNull = true;
| >| }
| >| else
| >| {
| >| try
| >| {
| >| mDate =
| >| DateTime.Parse(value);
| >| mIsNull = false;
| >| }
| >| catch
| >| {
| >| throw new
| >| ArgumentException("The string entered cannot be
| converted
| >| to a DateTime", "value");
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| string with optional formatting.
| >| /// </summary>
| >| /// <param name="Format">The format to
| >| return.</param>
| >| /// <returns>A string containing the
| >| correctly formatted date.</returns>
| >| public string GetValue(enumDateTimeFormat
| >| Format)
| >| {
| >| if(mIsNull)
| >| {
| >| return "";
| >| }
| >| else
| >| {
| >| switch(Format)
| >| {
| >| case
| >| enumDateTimeFormat.LongDateFormat:
| >| return
| >| mDate.ToLongDateString();
| >| case
| >| enumDateTimeFormat.LongTimeFormat:
| >| return
| >| mDate.ToLongTimeString();
| >| case
| >| enumDateTimeFormat.ShortDateFormat:
| >| return
| >| mDate.ToShortDateString();
| >| case
| >| enumDateTimeFormat.ShortTimeFormat:
| >| return
| >| mDate.ToShortTimeString();
| >| default:
| >| throw new
| >| UnhandledDateFormatException(Format);
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| ShortDateString.
| >| /// </summary>
| >| /// <returns></returns>
| >| public string GetValue()
| >| {
| >| return GetValue
| >| (enumDateTimeFormat.ShortDateFormat);
| >| }
| >| #endregion
| >|
| >| #region Public Override Methods
| >| /// <summary>
| >| /// Passes a string containing the date
| >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| >| /// </summary>
| >| /// <returns>The date returned. Passes an
| >| empty string for blank (null) dates.</returns>
| >| public override string ToString()
| >| {
| >| return GetValue();
| >| }
| >| #endregion
| >|
| >| #region Properties
| >| /// <summary>
| >| /// Returns the date of the
| >| OptionalDateTime as a DateTime type. Raises the
| >| /// <see
| >| cref="OptionalDateTimeIsNullException"/> if the
| >| OptionalDateTime is
| >| /// blank (null). Check the <see
| >| cref="IsNull"/> property before calling this
| >| /// method to avoid the exception.
| >| /// </summary>
| >| public DateTime GetDateTime
| >| {
| >| get
| >| {
| >| if(mIsNull)
| >| {
| >| throw new
| >| OptionalDateTimeIsNullException();
| >| }
| >| return mDate;
| >| }
| >| }
| >| /// <summary>
| >| /// Gets a boolean value indicating
| >| whether the OptionalDateTime is blank (null).
| >| /// </summary>
| >| public bool IsNull
| >| {
| >| get
| >| {
| >| return mIsNull;
| >| }
| >| }
| >| #endregion
| >| }
| >|
| >| thanks in advance
| >|
| >
| >.
| >
|
 
J

Jeffrey Tan[MSFT]

Sorry, there should be a "oldval=this.Value ;" in Custom DateTimePicker's
constructor.

Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Newsgroups: microsoft.public.dotnet.languages.csharp
| From: (e-mail address removed) ("Jeffrey Tan[MSFT]")
| Organization: Microsoft
| Date: Wed, 29 Oct 2003 03:12:29 GMT
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| MIME-Version: 1.0
| Content-Type: text/plain
| Content-Transfer-Encoding: 7bit
|
|
| Hi Guy,
|
| Sorry for letting you waiting so long time.
| In this time, I did a lot of research into DateTimePicker control and
| wanted to find a workaround for you.
| Here, I provide you 2 ways of workaround:
| First: override its OnCloseUp method and reset its value to its original
| value. But this is not enough, when you open the datetimepicker, you can
| use keyboard arrow to navigate the selection, and the value displayed
will
| also change in the textbox( For the moment, we call it textbox). I think
we
| should not let this happen, the value should stay the same. But just
reset
| value in the OnValueChanged method seems work well on keyboard
navigation,
| but will again change the value when closing the calendar.(It seems that
| the OnCloseUp abated). So I hooked into this control, and filter its
| MCN_SELCHANGE notification in WM_NOTIFY message.
|
| using System.Runtime .InteropServices ;
| public bool readonlyval=false;
| private DateTime oldval;
|
| protected override void OnCloseUp(EventArgs eventargs)
| {
| if(readonlyval==true)
| {
| this.Value =oldval;
| }
| oldval=this.Value ;
| base.OnCloseUp (eventargs);
| }
|
| private const int MCN_FIRST=-750;
| private const int MCN_SELCHANGE=MCN_FIRST + 1;
| private int WM_NOTIFY=0x004E;
|
| [StructLayout(LayoutKind.Sequential)]
| public struct NMHDR
| {
| public IntPtr hwndFrom;
| public int idfrom;
| public int code;
| }
|
| protected override void WndProc(ref Message m)
| {
| if(m.Msg==WM_NOTIFY)
| {
| if(m.HWnd==this.Handle)
| {
| NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
| if(nm1.code==MCN_SELCHANGE)
| {
| return;
| }
| }
| }
| base.WndProc (ref m);
| }
|
| I use Spy++ to find that the DateTimePicker control will receive
WM_NOTIFY
| message with MCN_SELCHANGE code when selection changes.
| All the const value MCN_SELCHANGE, MCN_FIRST can be found in the
C:\Program
| Files\Microsoft Visual Studio\VC98\Include directory *.h files.
|
| It works well on my machine. If you have any question, please feel free
to
| tell me.
| I will reply the second way of workaround in another reply post.
|
| Best regards
| Jeffrey Tan
| Microsoft Online Partner Support
| Get Secure! - www.microsoft.com/security
| This posting is provided "as is" with no warranties and confers no rights.
|
| --------------------
| | Content-Class: urn:content-classes:message
| | From: "guy" <[email protected]>
| | Sender: "guy" <[email protected]>
| | References: <[email protected]>
| <[email protected]>
| | Subject: RE: bug using Application.EnableVisualStyles() with
| datetimepicker control
| | Date: Tue, 28 Oct 2003 01:26:56 -0800
| | Lines: 601
| | Message-ID: <[email protected]>
| | MIME-Version: 1.0
| | Content-Type: text/plain;
| | charset="iso-8859-1"
| | Content-Transfer-Encoding: 7bit
| | X-Newsreader: Microsoft CDO for Windows 2000
| | Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| | X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| | Newsgroups: microsoft.public.dotnet.languages.csharp
| | Path: cpmsftngxa06.phx.gbl
| | Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.languages.csharp:194627
| | NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| | X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| |
| | Ok Jeffrey, ill wait for your reply
| |
| |
| |
| | >-----Original Message-----
| | >
| | >Hi Guy,
| | >
| | >It is an already known issue.
| | >I will do some research on this to find some workaround
| | for you.
| | >Thanks for you understanding.
| | >
| | >Best regards,
| | >Jeffrey Tan
| | >Microsoft Online Partner Support
| | >Get Secure! - www.microsoft.com/security
| | >This posting is provided "as is" with no warranties and
| | confers no rights.
| | >
| | >--------------------
| | >| Content-Class: urn:content-classes:message
| | >| From: "Guy" <[email protected]>
| | >| Sender: "Guy" <[email protected]>
| | >| Subject: bug using Application.EnableVisualStyles()
| | with datetimepicker
| | >control
| | >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| | >| Lines: 540
| | >| Message-ID: <[email protected]>
| | >| MIME-Version: 1.0
| | >| Content-Type: text/plain;
| | >| charset="iso-8859-1"
| | >| Content-Transfer-Encoding: 7bit
| | >| X-Newsreader: Microsoft CDO for Windows 2000
| | >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| | >| X-MimeOLE: Produced By Microsoft MimeOLE
| | V5.50.4910.0300
| | >| Newsgroups: microsoft.public.dotnet.languages.csharp
| | >| Path: cpmsftngxa06.phx.gbl
| | >| Xref: cpmsftngxa06.phx.gbl
| | microsoft.public.dotnet.languages.csharp:193774
| | >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| | >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| | >|
| | >| I have extended the datetimepicker control to
| | incorporate
| | >| a ReadOnly property.
| | >| I have used the new keyword to implement my own
| | version
| | >| of the value property, so that if readonly == true
| | then
| | >| it will not set the value of the control and will
| | leave
| | >| the checked status of the checkbox to false when a
| | user
| | >| selects a new date.
| | >|
| | >| this works fine when using the control on a win2k
| | machine
| | >| but if we use it on a win XP box and call
| | >| Application.EnableVisualStyles() then it seems to
| | ignore
| | >| my code and check the checkbox and set the value. this
| | is
| | >| extremely buggy behaviour! and also the value property
| | >| gets called twice (only once on a win2k box).
| | >|
| | >| i have also noticed behaviour changes in the
| | >| label.textalignment property when using XP Visual
| | styles
| | >| aswell. Below is my implementation of the extended
| | >| datetimepicker and also the new data type
| | >| (OptionalDateTime) that is used for the value
| | property...
| | >|
| | >| #####LockableDateTimePicker Source###########
| | >|
| | >| using System;
| | >| using System.Collections;
| | >| using System.ComponentModel;
| | >| using System.Drawing;
| | >| using System.Data;
| | >| using System.Windows.Forms;
| | >| using HCS.DataTypes;
| | >|
| | >| namespace HCS.Generic.UI.Controls
| | >| {
| | >| /// <summary>
| | >| /// LockableDateTimePicker is for selecting
| | >| dates. It manipulates the OptionalDateTime
| | >| /// class to allow null dates to be handled.
| | >| /// </summary>
| | >| public class LockableDateTimePicker :
| | >| DateTimePicker
| | >| {
| | >| #region Clean Up Code
| | >|
| | >| /// <summary>
| | >| /// Clean up any resources being used.
| | >| /// </summary>
| | >| protected override void Dispose( bool
| | >| disposing )
| | >| {
| | >| if( disposing )
| | >| {
| | >| if(components != null)
| | >| {
| | >| components.Dispose
| | >| ();
| | >| }
| | >| }
| | >| base.Dispose( disposing );
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Component Designer generated code
| | >| /// <summary>
| | >| /// Required method for Designer support -
| | >| do not modify
| | >| /// the contents of this method with the
| | >| code editor.
| | >| /// </summary>
| | >| private void InitializeComponent()
| | >| {
| | >| components = new
| | >| System.ComponentModel.Container();
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >|
| | >| private System.ComponentModel.Container
| | >| components = null;
| | >| private bool mReadOnly;
| | >| private DateTime mDateTime;
| | >| private Color mBackColor;
| | >| private Color mLockedColor;
| | >| private bool mChecked;
| | >|
| | >| #endregion
| | >|
| | >| #region Events
| | >|
| | >| public event OnReadOnlyChangedDelegate
| | >| OnReadOnlyChanged;
| | >|
| | >| #endregion
| | >|
| | >| #region EventArgs and Delegates
| | >|
| | >| public class OnReadOnlyChangedEventArgs :
| | >| EventArgs
| | >| {
| | >| private bool mReadOnly;
| | >|
| | >| public OnReadOnlyChangedEventArgs
| | >| (bool ReadOnly)
| | >| {
| | >| mReadOnly = ReadOnly;
| | >| }
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| }
| | >| }
| | >| public delegate void
| | >| OnReadOnlyChangedDelegate(object sender,
| | >| OnReadOnlyChangedEventArgs e);
| | >|
| | >| #endregion
| | >|
| | >| #region Constructor
| | >|
| | >| public LockableDateTimePicker()
| | >| {
| | >| // This call is required by the
| | >| Windows.Forms Form Designer.
| | >| InitializeComponent();
| | >|
| | >| mBackColor =
| | >| base.CalendarMonthBackground;
| | >| mLockedColor =
| | >| base.CalendarMonthBackground;
| | >|
| | >| //Set defaults for this control
| | >| base.Format =
| | >| DateTimePickerFormat.Short;
| | >|
| | >| //Make sure that our date backup
| | >| is populated
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Properties
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| set
| | >| {
| | >| if(value)
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mLockedColor;
| | >| }
| | >| else
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mBackColor;
| | >| }
| | >|
| | >| mReadOnly = value;
| | >| if(OnReadOnlyChanged !=
| | >| null)
| | >| {
| | >| OnReadOnlyChanged
| | >| (this, new OnReadOnlyChangedEventArgs(value));
| | >| }
| | >| }
| | >| }
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public Color LockedColor
| | >| {
| | >| get
| | >| {
| | >| return mLockedColor;
| | >| }
| | >| set
| | >| {
| | >| mLockedColor = value;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Overridden Properties
| | >| public override Color BackColor
| | >| {
| | >| get
| | >| {
| | >| return base.BackColor;
| | >| }
| | >| set
| | >| {
| | >| mBackColor = value;
| | >| if(!mReadOnly)
| | >| {
| | >| base.BackColor =
| | >| value;
| | >| }
| | >| }
| | >| }
| | >| public new OptionalDateTime Value
| | >| {
| | >| set
| | >| {
| | >| if(value.GetValue() == "")
| | >| {
| | >| base.Checked =
| | >| false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(value.GetValue());
| | >| }
| | >|
| | >| }
| | >| get
| | >| {
| | >| if(base.Checked)
| | >| {
| | >| return new
| | >| OptionalDateTime(base.Value);
| | >| }
| | >| else
| | >| {
| | >| return new
| | >| OptionalDateTime();
| | >| }
| | >| }
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Overridden Events
| | >|
| | >| protected override void OnValueChanged
| | >| (EventArgs eventargs)
| | >| {
| | >| base.OnValueChanged (eventargs);
| | >|
| | >| if(mReadOnly)
| | >| {
| | >| //We need to set the
| | >| value of the control back to
| | >| //the stored value, since
| | >| it is read only
| | >| if(base.Value !=
| | >| mDateTime)
| | >| {
| | >| base.Value =
| | >| mDateTime;
| | >| }
| | >| if(base.Checked !=
| | >| mChecked)
| | >| {
| | >| base.Checked =
| | >| mChecked;
| | >| }
| | >| }
| | >| else
| | >| {
| | >| //Store the value for
| | >| when it's read only
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| public void Initialise(OptionalDateTime
| | >| Value)
| | >| {
| | >| //Temporarily set the control to
| | >| not ReadOnly.
| | >| bool mTempReadOnly = mReadOnly;
| | >| if(mReadOnly)
| | >| {
| | >| mReadOnly = false;
| | >| }
| | >|
| | >| if(Value.GetValue() == "")
| | >| {
| | >| base.Checked = false;
| | >| mChecked = false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(Value.GetValue());
| | >| base.Checked = true;
| | >| mDateTime = base.Value;
| | >| mChecked = true;
| | >| }
| | >|
| | >| //Make sure the ReadOnly value is
| | >| returned to normal
| | >| mReadOnly = mTempReadOnly;
| | >| }
| | >| public void Initialise(DateTime Value)
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| (Value));
| | >| }
| | >| public void Initialise()
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| ());
| | >| }
| | >| #endregion
| | >| }
| | >| }
| | >|
| | >| ##############OptionalDateTime Source##########
| | >|
| | >| [Serializable()]
| | >| public class OptionalDateTime
| | >| {
| | >| #region Enum
| | >| /// <summary>
| | >| /// Formats available - extend as
| | >| required, but remember to update <see
| | cref="GetValue"/>.
| | >| /// </summary>
| | >| public enum enumDateTimeFormat
| | >| {
| | >| /// <summary>
| | >| /// LongDateFormat
| | >| /// </summary>
| | >| LongDateFormat,
| | >| /// <summary>
| | >| /// LongTimeFormat
| | >| /// </summary>
| | >| LongTimeFormat,
| | >| /// <summary>
| | >| /// ShortDateFormat
| | >| /// </summary>
| | >| ShortDateFormat,
| | >| /// <summary>
| | >| /// ShortTimeFormat
| | >| /// </summary>
| | >| ShortTimeFormat
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >| private DateTime mDate;
| | >| private bool mIsNull;
| | >| #endregion
| | >|
| | >| #region Constructor
| | >| /// <summary>
| | >| /// Constructor - initialises a null
| | >| OptionalDateTime
| | >| /// </summary>
| | >| public OptionalDateTime()
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a string.
| | >| /// If the string is not a valid
| | >| DateTime, the object is set to contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public OptionalDateTime(string value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A DateTime value
| | >| type.</param>
| | >| public OptionalDateTime(DateTime value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A
| | >| DateTime.</param>
| | >| public void SetValue(DateTime value)
| | >| {
| | >| mDate = value;
| | >| mIsNull = false;
| | >| }
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a string. If the string is not a valid
| | >| /// DateTime, the object is set to
| | >| contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public void SetValue(string value)
| | >| {
| | >| if(value == null || value == "")
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| else
| | >| {
| | >| try
| | >| {
| | >| mDate =
| | >| DateTime.Parse(value);
| | >| mIsNull = false;
| | >| }
| | >| catch
| | >| {
| | >| throw new
| | >| ArgumentException("The string entered cannot be
| | converted
| | >| to a DateTime", "value");
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| string with optional formatting.
| | >| /// </summary>
| | >| /// <param name="Format">The format to
| | >| return.</param>
| | >| /// <returns>A string containing the
| | >| correctly formatted date.</returns>
| | >| public string GetValue(enumDateTimeFormat
| | >| Format)
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| return "";
| | >| }
| | >| else
| | >| {
| | >| switch(Format)
| | >| {
| | >| case
| | >| enumDateTimeFormat.LongDateFormat:
| | >| return
| | >| mDate.ToLongDateString();
| | >| case
| | >| enumDateTimeFormat.LongTimeFormat:
| | >| return
| | >| mDate.ToLongTimeString();
| | >| case
| | >| enumDateTimeFormat.ShortDateFormat:
| | >| return
| | >| mDate.ToShortDateString();
| | >| case
| | >| enumDateTimeFormat.ShortTimeFormat:
| | >| return
| | >| mDate.ToShortTimeString();
| | >| default:
| | >| throw new
| | >| UnhandledDateFormatException(Format);
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| ShortDateString.
| | >| /// </summary>
| | >| /// <returns></returns>
| | >| public string GetValue()
| | >| {
| | >| return GetValue
| | >| (enumDateTimeFormat.ShortDateFormat);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Override Methods
| | >| /// <summary>
| | >| /// Passes a string containing the date
| | >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| | >| /// </summary>
| | >| /// <returns>The date returned. Passes an
| | >| empty string for blank (null) dates.</returns>
| | >| public override string ToString()
| | >| {
| | >| return GetValue();
| | >| }
| | >| #endregion
| | >|
| | >| #region Properties
| | >| /// <summary>
| | >| /// Returns the date of the
| | >| OptionalDateTime as a DateTime type. Raises the
| | >| /// <see
| | >| cref="OptionalDateTimeIsNullException"/> if the
| | >| OptionalDateTime is
| | >| /// blank (null). Check the <see
| | >| cref="IsNull"/> property before calling this
| | >| /// method to avoid the exception.
| | >| /// </summary>
| | >| public DateTime GetDateTime
| | >| {
| | >| get
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| throw new
| | >| OptionalDateTimeIsNullException();
| | >| }
| | >| return mDate;
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Gets a boolean value indicating
| | >| whether the OptionalDateTime is blank (null).
| | >| /// </summary>
| | >| public bool IsNull
| | >| {
| | >| get
| | >| {
| | >| return mIsNull;
| | >| }
| | >| }
| | >| #endregion
| | >| }
| | >|
| | >| thanks in advance
| | >|
| | >
| | >.
| | >
| |
|
 
J

Jeffrey Tan[MSFT]

Hi Guy,

Sorry for letting you waiting so long time.
In this time, I did a lot of research into DateTimePicker control and
wanted to find a workaround for you.
Here, I provide you 2 ways of workaround:
First: override its OnCloseUp method and reset its value to its original
value. But this is not enough, when you open the datetimepicker, you can
use keyboard arrow to navigate the selection, and the value displayed will
also change in the textbox( For the moment, we call it textbox). I think we
should not let this happen, the value should stay the same. But just reset
value in the OnValueChanged method seems work well on keyboard navigation,
but will again change the value when closing the calendar.(It seems that
the OnCloseUp abated). So I hooked into this control, and filter its
MCN_SELCHANGE notification in WM_NOTIFY message.

using System.Runtime .InteropServices ;
public bool readonlyval=false;
private DateTime oldval;

oldval=this.Value; // in this control's constructor

protected override void OnCloseUp(EventArgs eventargs)
{
if(readonlyval==true)
{
this.Value =oldval;
}
oldval=this.Value ;
base.OnCloseUp (eventargs);
}

private const int MCN_FIRST=-750;
private const int MCN_SELCHANGE=MCN_FIRST + 1;
private int WM_NOTIFY=0x004E;

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public int idfrom;
public int code;
}

protected override void WndProc(ref Message m)
{
if(this.oldval==true)
{
if(m.Msg==WM_NOTIFY)
{
if(m.HWnd==this.Handle)
{
NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
if(nm1.code==MCN_SELCHANGE)
{
return;
}
}
}
base.WndProc (ref m);
}
}

I use Spy++ to find that the DateTimePicker control will receive WM_NOTIFY
message with MCN_SELCHANGE code when selection changes.
All the const value MCN_SELCHANGE, MCN_FIRST can be found in the C:\Program
Files\Microsoft Visual Studio\VC98\Include directory *.h files.

It works well on my machine. If you have any question, please feel free to
tell me.
I will reply the second way of workaround in another reply post.

Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "guy" <[email protected]>
| Sender: "guy" <[email protected]>
| References: <[email protected]>
<[email protected]>
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| Date: Tue, 28 Oct 2003 01:26:56 -0800
| Lines: 601
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:194627
| NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Ok Jeffrey, ill wait for your reply
|
|
|
| >-----Original Message-----
| >
| >Hi Guy,
| >
| >It is an already known issue.
| >I will do some research on this to find some workaround
| for you.
| >Thanks for you understanding.
| >
| >Best regards,
| >Jeffrey Tan
| >Microsoft Online Partner Support
| >Get Secure! - www.microsoft.com/security
| >This posting is provided "as is" with no warranties and
| confers no rights.
| >
| >--------------------
| >| Content-Class: urn:content-classes:message
| >| From: "Guy" <[email protected]>
| >| Sender: "Guy" <[email protected]>
| >| Subject: bug using Application.EnableVisualStyles()
| with datetimepicker
| >control
| >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| >| Lines: 540
| >| Message-ID: <[email protected]>
| >| MIME-Version: 1.0
| >| Content-Type: text/plain;
| >| charset="iso-8859-1"
| >| Content-Transfer-Encoding: 7bit
| >| X-Newsreader: Microsoft CDO for Windows 2000
| >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| >| X-MimeOLE: Produced By Microsoft MimeOLE
| V5.50.4910.0300
| >| Newsgroups: microsoft.public.dotnet.languages.csharp
| >| Path: cpmsftngxa06.phx.gbl
| >| Xref: cpmsftngxa06.phx.gbl
| microsoft.public.dotnet.languages.csharp:193774
| >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| >|
| >| I have extended the datetimepicker control to
| incorporate
| >| a ReadOnly property.
| >| I have used the new keyword to implement my own
| version
| >| of the value property, so that if readonly == true
| then
| >| it will not set the value of the control and will
| leave
| >| the checked status of the checkbox to false when a
| user
| >| selects a new date.
| >|
| >| this works fine when using the control on a win2k
| machine
| >| but if we use it on a win XP box and call
| >| Application.EnableVisualStyles() then it seems to
| ignore
| >| my code and check the checkbox and set the value. this
| is
| >| extremely buggy behaviour! and also the value property
| >| gets called twice (only once on a win2k box).
| >|
| >| i have also noticed behaviour changes in the
| >| label.textalignment property when using XP Visual
| styles
| >| aswell. Below is my implementation of the extended
| >| datetimepicker and also the new data type
| >| (OptionalDateTime) that is used for the value
| property...
| >|
| >| #####LockableDateTimePicker Source###########
| >|
| >| using System;
| >| using System.Collections;
| >| using System.ComponentModel;
| >| using System.Drawing;
| >| using System.Data;
| >| using System.Windows.Forms;
| >| using HCS.DataTypes;
| >|
| >| namespace HCS.Generic.UI.Controls
| >| {
| >| /// <summary>
| >| /// LockableDateTimePicker is for selecting
| >| dates. It manipulates the OptionalDateTime
| >| /// class to allow null dates to be handled.
| >| /// </summary>
| >| public class LockableDateTimePicker :
| >| DateTimePicker
| >| {
| >| #region Clean Up Code
| >|
| >| /// <summary>
| >| /// Clean up any resources being used.
| >| /// </summary>
| >| protected override void Dispose( bool
| >| disposing )
| >| {
| >| if( disposing )
| >| {
| >| if(components != null)
| >| {
| >| components.Dispose
| >| ();
| >| }
| >| }
| >| base.Dispose( disposing );
| >| }
| >|
| >| #endregion
| >|
| >| #region Component Designer generated code
| >| /// <summary>
| >| /// Required method for Designer support -
| >| do not modify
| >| /// the contents of this method with the
| >| code editor.
| >| /// </summary>
| >| private void InitializeComponent()
| >| {
| >| components = new
| >| System.ComponentModel.Container();
| >| }
| >| #endregion
| >|
| >| #region Fields
| >|
| >| private System.ComponentModel.Container
| >| components = null;
| >| private bool mReadOnly;
| >| private DateTime mDateTime;
| >| private Color mBackColor;
| >| private Color mLockedColor;
| >| private bool mChecked;
| >|
| >| #endregion
| >|
| >| #region Events
| >|
| >| public event OnReadOnlyChangedDelegate
| >| OnReadOnlyChanged;
| >|
| >| #endregion
| >|
| >| #region EventArgs and Delegates
| >|
| >| public class OnReadOnlyChangedEventArgs :
| >| EventArgs
| >| {
| >| private bool mReadOnly;
| >|
| >| public OnReadOnlyChangedEventArgs
| >| (bool ReadOnly)
| >| {
| >| mReadOnly = ReadOnly;
| >| }
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| }
| >| }
| >| public delegate void
| >| OnReadOnlyChangedDelegate(object sender,
| >| OnReadOnlyChangedEventArgs e);
| >|
| >| #endregion
| >|
| >| #region Constructor
| >|
| >| public LockableDateTimePicker()
| >| {
| >| // This call is required by the
| >| Windows.Forms Form Designer.
| >| InitializeComponent();
| >|
| >| mBackColor =
| >| base.CalendarMonthBackground;
| >| mLockedColor =
| >| base.CalendarMonthBackground;
| >|
| >| //Set defaults for this control
| >| base.Format =
| >| DateTimePickerFormat.Short;
| >|
| >| //Make sure that our date backup
| >| is populated
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >|
| >| #endregion
| >|
| >| #region Properties
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| set
| >| {
| >| if(value)
| >| {
| >|
| >| base.CalendarMonthBackground = mLockedColor;
| >| }
| >| else
| >| {
| >|
| >| base.CalendarMonthBackground = mBackColor;
| >| }
| >|
| >| mReadOnly = value;
| >| if(OnReadOnlyChanged !=
| >| null)
| >| {
| >| OnReadOnlyChanged
| >| (this, new OnReadOnlyChangedEventArgs(value));
| >| }
| >| }
| >| }
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public Color LockedColor
| >| {
| >| get
| >| {
| >| return mLockedColor;
| >| }
| >| set
| >| {
| >| mLockedColor = value;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Overridden Properties
| >| public override Color BackColor
| >| {
| >| get
| >| {
| >| return base.BackColor;
| >| }
| >| set
| >| {
| >| mBackColor = value;
| >| if(!mReadOnly)
| >| {
| >| base.BackColor =
| >| value;
| >| }
| >| }
| >| }
| >| public new OptionalDateTime Value
| >| {
| >| set
| >| {
| >| if(value.GetValue() == "")
| >| {
| >| base.Checked =
| >| false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(value.GetValue());
| >| }
| >|
| >| }
| >| get
| >| {
| >| if(base.Checked)
| >| {
| >| return new
| >| OptionalDateTime(base.Value);
| >| }
| >| else
| >| {
| >| return new
| >| OptionalDateTime();
| >| }
| >| }
| >| }
| >| #endregion
| >|
| >| #region Public Overridden Events
| >|
| >| protected override void OnValueChanged
| >| (EventArgs eventargs)
| >| {
| >| base.OnValueChanged (eventargs);
| >|
| >| if(mReadOnly)
| >| {
| >| //We need to set the
| >| value of the control back to
| >| //the stored value, since
| >| it is read only
| >| if(base.Value !=
| >| mDateTime)
| >| {
| >| base.Value =
| >| mDateTime;
| >| }
| >| if(base.Checked !=
| >| mChecked)
| >| {
| >| base.Checked =
| >| mChecked;
| >| }
| >| }
| >| else
| >| {
| >| //Store the value for
| >| when it's read only
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Methods
| >| public void Initialise(OptionalDateTime
| >| Value)
| >| {
| >| //Temporarily set the control to
| >| not ReadOnly.
| >| bool mTempReadOnly = mReadOnly;
| >| if(mReadOnly)
| >| {
| >| mReadOnly = false;
| >| }
| >|
| >| if(Value.GetValue() == "")
| >| {
| >| base.Checked = false;
| >| mChecked = false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(Value.GetValue());
| >| base.Checked = true;
| >| mDateTime = base.Value;
| >| mChecked = true;
| >| }
| >|
| >| //Make sure the ReadOnly value is
| >| returned to normal
| >| mReadOnly = mTempReadOnly;
| >| }
| >| public void Initialise(DateTime Value)
| >| {
| >| Initialise(new OptionalDateTime
| >| (Value));
| >| }
| >| public void Initialise()
| >| {
| >| Initialise(new OptionalDateTime
| >| ());
| >| }
| >| #endregion
| >| }
| >| }
| >|
| >| ##############OptionalDateTime Source##########
| >|
| >| [Serializable()]
| >| public class OptionalDateTime
| >| {
| >| #region Enum
| >| /// <summary>
| >| /// Formats available - extend as
| >| required, but remember to update <see
| cref="GetValue"/>.
| >| /// </summary>
| >| public enum enumDateTimeFormat
| >| {
| >| /// <summary>
| >| /// LongDateFormat
| >| /// </summary>
| >| LongDateFormat,
| >| /// <summary>
| >| /// LongTimeFormat
| >| /// </summary>
| >| LongTimeFormat,
| >| /// <summary>
| >| /// ShortDateFormat
| >| /// </summary>
| >| ShortDateFormat,
| >| /// <summary>
| >| /// ShortTimeFormat
| >| /// </summary>
| >| ShortTimeFormat
| >| }
| >| #endregion
| >|
| >| #region Fields
| >| private DateTime mDate;
| >| private bool mIsNull;
| >| #endregion
| >|
| >| #region Constructor
| >| /// <summary>
| >| /// Constructor - initialises a null
| >| OptionalDateTime
| >| /// </summary>
| >| public OptionalDateTime()
| >| {
| >| mIsNull = true;
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a string.
| >| /// If the string is not a valid
| >| DateTime, the object is set to contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public OptionalDateTime(string value)
| >| {
| >| SetValue(value);
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A DateTime value
| >| type.</param>
| >| public OptionalDateTime(DateTime value)
| >| {
| >| SetValue(value);
| >| }
| >| #endregion
| >|
| >| #region Public Methods
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A
| >| DateTime.</param>
| >| public void SetValue(DateTime value)
| >| {
| >| mDate = value;
| >| mIsNull = false;
| >| }
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a string. If the string is not a valid
| >| /// DateTime, the object is set to
| >| contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public void SetValue(string value)
| >| {
| >| if(value == null || value == "")
| >| {
| >| mIsNull = true;
| >| }
| >| else
| >| {
| >| try
| >| {
| >| mDate =
| >| DateTime.Parse(value);
| >| mIsNull = false;
| >| }
| >| catch
| >| {
| >| throw new
| >| ArgumentException("The string entered cannot be
| converted
| >| to a DateTime", "value");
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| string with optional formatting.
| >| /// </summary>
| >| /// <param name="Format">The format to
| >| return.</param>
| >| /// <returns>A string containing the
| >| correctly formatted date.</returns>
| >| public string GetValue(enumDateTimeFormat
| >| Format)
| >| {
| >| if(mIsNull)
| >| {
| >| return "";
| >| }
| >| else
| >| {
| >| switch(Format)
| >| {
| >| case
| >| enumDateTimeFormat.LongDateFormat:
| >| return
| >| mDate.ToLongDateString();
| >| case
| >| enumDateTimeFormat.LongTimeFormat:
| >| return
| >| mDate.ToLongTimeString();
| >| case
| >| enumDateTimeFormat.ShortDateFormat:
| >| return
| >| mDate.ToShortDateString();
| >| case
| >| enumDateTimeFormat.ShortTimeFormat:
| >| return
| >| mDate.ToShortTimeString();
| >| default:
| >| throw new
| >| UnhandledDateFormatException(Format);
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| ShortDateString.
| >| /// </summary>
| >| /// <returns></returns>
| >| public string GetValue()
| >| {
| >| return GetValue
| >| (enumDateTimeFormat.ShortDateFormat);
| >| }
| >| #endregion
| >|
| >| #region Public Override Methods
| >| /// <summary>
| >| /// Passes a string containing the date
| >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| >| /// </summary>
| >| /// <returns>The date returned. Passes an
| >| empty string for blank (null) dates.</returns>
| >| public override string ToString()
| >| {
| >| return GetValue();
| >| }
| >| #endregion
| >|
| >| #region Properties
| >| /// <summary>
| >| /// Returns the date of the
| >| OptionalDateTime as a DateTime type. Raises the
| >| /// <see
| >| cref="OptionalDateTimeIsNullException"/> if the
| >| OptionalDateTime is
| >| /// blank (null). Check the <see
| >| cref="IsNull"/> property before calling this
| >| /// method to avoid the exception.
| >| /// </summary>
| >| public DateTime GetDateTime
| >| {
| >| get
| >| {
| >| if(mIsNull)
| >| {
| >| throw new
| >| OptionalDateTimeIsNullException();
| >| }
| >| return mDate;
| >| }
| >| }
| >| /// <summary>
| >| /// Gets a boolean value indicating
| >| whether the OptionalDateTime is blank (null).
| >| /// </summary>
| >| public bool IsNull
| >| {
| >| get
| >| {
| >| return mIsNull;
| >| }
| >| }
| >| #endregion
| >| }
| >|
| >| thanks in advance
| >|
| >
| >.
| >
|
 
J

Jeffrey Tan[MSFT]

Hi Guy,

Sorry for letting you waiting so long time.
In this time, I did a lot of research into DateTimePicker control and
wanted to find a workaround for you.
Here, I provide you 2 ways of workaround:
First: override its OnCloseUp method and reset its value to its original
value. But this is not enough, when you open the datetimepicker, you can
use keyboard arrow to navigate the selection, and the value displayed will
also change in the textbox( For the moment, we call it textbox). I think we
should not let this happen, the value should stay the same. But just reset
value in the OnValueChanged method seems work well on keyboard navigation,
but will again change the value when closing the calendar.(It seems that
the OnCloseUp abated). So I hooked into this control, and filter its
MCN_SELCHANGE notification in WM_NOTIFY message.

using System.Runtime .InteropServices ;
public bool readonlyval=false;
private DateTime oldval;

oldval=this.Value; // in this control's constructor

protected override void OnCloseUp(EventArgs eventargs)
{
if(readonlyval==true)
{
this.Value =oldval;
}
oldval=this.Value ;
base.OnCloseUp (eventargs);
}

private const int MCN_FIRST=-750;
private const int MCN_SELCHANGE=MCN_FIRST + 1;
private int WM_NOTIFY=0x004E;

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public int idfrom;
public int code;
}

protected override void WndProc(ref Message m)
{
if(this.readonlyval==true)
{
if(m.Msg==WM_NOTIFY)
{
if(m.HWnd==this.Handle)
{
NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
if(nm1.code==MCN_SELCHANGE)
{
return;
}
}
}
base.WndProc (ref m);
}
}

I use Spy++ to find that the DateTimePicker control will receive WM_NOTIFY
message with MCN_SELCHANGE code when selection changes.
All the const value MCN_SELCHANGE, MCN_FIRST can be found in the C:\Program
Files\Microsoft Visual Studio\VC98\Include directory *.h files.

It works well on my machine. If you have any question, please feel free to
tell me.
I will reply the second way of workaround in another reply post.

Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "guy" <[email protected]>
| Sender: "guy" <[email protected]>
| References: <[email protected]>
<[email protected]>
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| Date: Tue, 28 Oct 2003 01:26:56 -0800
| Lines: 601
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:194627
| NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Ok Jeffrey, ill wait for your reply
|
|
|
| >-----Original Message-----
| >
| >Hi Guy,
| >
| >It is an already known issue.
| >I will do some research on this to find some workaround
| for you.
| >Thanks for you understanding.
| >
| >Best regards,
| >Jeffrey Tan
| >Microsoft Online Partner Support
| >Get Secure! - www.microsoft.com/security
| >This posting is provided "as is" with no warranties and
| confers no rights.
| >
| >--------------------
| >| Content-Class: urn:content-classes:message
| >| From: "Guy" <[email protected]>
| >| Sender: "Guy" <[email protected]>
| >| Subject: bug using Application.EnableVisualStyles()
| with datetimepicker
| >control
| >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| >| Lines: 540
| >| Message-ID: <[email protected]>
| >| MIME-Version: 1.0
| >| Content-Type: text/plain;
| >| charset="iso-8859-1"
| >| Content-Transfer-Encoding: 7bit
| >| X-Newsreader: Microsoft CDO for Windows 2000
| >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| >| X-MimeOLE: Produced By Microsoft MimeOLE
| V5.50.4910.0300
| >| Newsgroups: microsoft.public.dotnet.languages.csharp
| >| Path: cpmsftngxa06.phx.gbl
| >| Xref: cpmsftngxa06.phx.gbl
| microsoft.public.dotnet.languages.csharp:193774
| >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| >|
| >| I have extended the datetimepicker control to
| incorporate
| >| a ReadOnly property.
| >| I have used the new keyword to implement my own
| version
| >| of the value property, so that if readonly == true
| then
| >| it will not set the value of the control and will
| leave
| >| the checked status of the checkbox to false when a
| user
| >| selects a new date.
| >|
| >| this works fine when using the control on a win2k
| machine
| >| but if we use it on a win XP box and call
| >| Application.EnableVisualStyles() then it seems to
| ignore
| >| my code and check the checkbox and set the value. this
| is
| >| extremely buggy behaviour! and also the value property
| >| gets called twice (only once on a win2k box).
| >|
| >| i have also noticed behaviour changes in the
| >| label.textalignment property when using XP Visual
| styles
| >| aswell. Below is my implementation of the extended
| >| datetimepicker and also the new data type
| >| (OptionalDateTime) that is used for the value
| property...
| >|
| >| #####LockableDateTimePicker Source###########
| >|
| >| using System;
| >| using System.Collections;
| >| using System.ComponentModel;
| >| using System.Drawing;
| >| using System.Data;
| >| using System.Windows.Forms;
| >| using HCS.DataTypes;
| >|
| >| namespace HCS.Generic.UI.Controls
| >| {
| >| /// <summary>
| >| /// LockableDateTimePicker is for selecting
| >| dates. It manipulates the OptionalDateTime
| >| /// class to allow null dates to be handled.
| >| /// </summary>
| >| public class LockableDateTimePicker :
| >| DateTimePicker
| >| {
| >| #region Clean Up Code
| >|
| >| /// <summary>
| >| /// Clean up any resources being used.
| >| /// </summary>
| >| protected override void Dispose( bool
| >| disposing )
| >| {
| >| if( disposing )
| >| {
| >| if(components != null)
| >| {
| >| components.Dispose
| >| ();
| >| }
| >| }
| >| base.Dispose( disposing );
| >| }
| >|
| >| #endregion
| >|
| >| #region Component Designer generated code
| >| /// <summary>
| >| /// Required method for Designer support -
| >| do not modify
| >| /// the contents of this method with the
| >| code editor.
| >| /// </summary>
| >| private void InitializeComponent()
| >| {
| >| components = new
| >| System.ComponentModel.Container();
| >| }
| >| #endregion
| >|
| >| #region Fields
| >|
| >| private System.ComponentModel.Container
| >| components = null;
| >| private bool mReadOnly;
| >| private DateTime mDateTime;
| >| private Color mBackColor;
| >| private Color mLockedColor;
| >| private bool mChecked;
| >|
| >| #endregion
| >|
| >| #region Events
| >|
| >| public event OnReadOnlyChangedDelegate
| >| OnReadOnlyChanged;
| >|
| >| #endregion
| >|
| >| #region EventArgs and Delegates
| >|
| >| public class OnReadOnlyChangedEventArgs :
| >| EventArgs
| >| {
| >| private bool mReadOnly;
| >|
| >| public OnReadOnlyChangedEventArgs
| >| (bool ReadOnly)
| >| {
| >| mReadOnly = ReadOnly;
| >| }
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| }
| >| }
| >| public delegate void
| >| OnReadOnlyChangedDelegate(object sender,
| >| OnReadOnlyChangedEventArgs e);
| >|
| >| #endregion
| >|
| >| #region Constructor
| >|
| >| public LockableDateTimePicker()
| >| {
| >| // This call is required by the
| >| Windows.Forms Form Designer.
| >| InitializeComponent();
| >|
| >| mBackColor =
| >| base.CalendarMonthBackground;
| >| mLockedColor =
| >| base.CalendarMonthBackground;
| >|
| >| //Set defaults for this control
| >| base.Format =
| >| DateTimePickerFormat.Short;
| >|
| >| //Make sure that our date backup
| >| is populated
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >|
| >| #endregion
| >|
| >| #region Properties
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public bool ReadOnly
| >| {
| >| get
| >| {
| >| return mReadOnly;
| >| }
| >| set
| >| {
| >| if(value)
| >| {
| >|
| >| base.CalendarMonthBackground = mLockedColor;
| >| }
| >| else
| >| {
| >|
| >| base.CalendarMonthBackground = mBackColor;
| >| }
| >|
| >| mReadOnly = value;
| >| if(OnReadOnlyChanged !=
| >| null)
| >| {
| >| OnReadOnlyChanged
| >| (this, new OnReadOnlyChangedEventArgs(value));
| >| }
| >| }
| >| }
| >|
| >| [DesignerSerializationVisibility
| >| (DesignerSerializationVisibility.Visible)]
| >| public Color LockedColor
| >| {
| >| get
| >| {
| >| return mLockedColor;
| >| }
| >| set
| >| {
| >| mLockedColor = value;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Overridden Properties
| >| public override Color BackColor
| >| {
| >| get
| >| {
| >| return base.BackColor;
| >| }
| >| set
| >| {
| >| mBackColor = value;
| >| if(!mReadOnly)
| >| {
| >| base.BackColor =
| >| value;
| >| }
| >| }
| >| }
| >| public new OptionalDateTime Value
| >| {
| >| set
| >| {
| >| if(value.GetValue() == "")
| >| {
| >| base.Checked =
| >| false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(value.GetValue());
| >| }
| >|
| >| }
| >| get
| >| {
| >| if(base.Checked)
| >| {
| >| return new
| >| OptionalDateTime(base.Value);
| >| }
| >| else
| >| {
| >| return new
| >| OptionalDateTime();
| >| }
| >| }
| >| }
| >| #endregion
| >|
| >| #region Public Overridden Events
| >|
| >| protected override void OnValueChanged
| >| (EventArgs eventargs)
| >| {
| >| base.OnValueChanged (eventargs);
| >|
| >| if(mReadOnly)
| >| {
| >| //We need to set the
| >| value of the control back to
| >| //the stored value, since
| >| it is read only
| >| if(base.Value !=
| >| mDateTime)
| >| {
| >| base.Value =
| >| mDateTime;
| >| }
| >| if(base.Checked !=
| >| mChecked)
| >| {
| >| base.Checked =
| >| mChecked;
| >| }
| >| }
| >| else
| >| {
| >| //Store the value for
| >| when it's read only
| >| mDateTime = base.Value;
| >| mChecked = base.Checked;
| >| }
| >| }
| >|
| >| #endregion
| >|
| >| #region Public Methods
| >| public void Initialise(OptionalDateTime
| >| Value)
| >| {
| >| //Temporarily set the control to
| >| not ReadOnly.
| >| bool mTempReadOnly = mReadOnly;
| >| if(mReadOnly)
| >| {
| >| mReadOnly = false;
| >| }
| >|
| >| if(Value.GetValue() == "")
| >| {
| >| base.Checked = false;
| >| mChecked = false;
| >| }
| >| else
| >| {
| >| base.Value =
| >| DateTime.Parse(Value.GetValue());
| >| base.Checked = true;
| >| mDateTime = base.Value;
| >| mChecked = true;
| >| }
| >|
| >| //Make sure the ReadOnly value is
| >| returned to normal
| >| mReadOnly = mTempReadOnly;
| >| }
| >| public void Initialise(DateTime Value)
| >| {
| >| Initialise(new OptionalDateTime
| >| (Value));
| >| }
| >| public void Initialise()
| >| {
| >| Initialise(new OptionalDateTime
| >| ());
| >| }
| >| #endregion
| >| }
| >| }
| >|
| >| ##############OptionalDateTime Source##########
| >|
| >| [Serializable()]
| >| public class OptionalDateTime
| >| {
| >| #region Enum
| >| /// <summary>
| >| /// Formats available - extend as
| >| required, but remember to update <see
| cref="GetValue"/>.
| >| /// </summary>
| >| public enum enumDateTimeFormat
| >| {
| >| /// <summary>
| >| /// LongDateFormat
| >| /// </summary>
| >| LongDateFormat,
| >| /// <summary>
| >| /// LongTimeFormat
| >| /// </summary>
| >| LongTimeFormat,
| >| /// <summary>
| >| /// ShortDateFormat
| >| /// </summary>
| >| ShortDateFormat,
| >| /// <summary>
| >| /// ShortTimeFormat
| >| /// </summary>
| >| ShortTimeFormat
| >| }
| >| #endregion
| >|
| >| #region Fields
| >| private DateTime mDate;
| >| private bool mIsNull;
| >| #endregion
| >|
| >| #region Constructor
| >| /// <summary>
| >| /// Constructor - initialises a null
| >| OptionalDateTime
| >| /// </summary>
| >| public OptionalDateTime()
| >| {
| >| mIsNull = true;
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a string.
| >| /// If the string is not a valid
| >| DateTime, the object is set to contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public OptionalDateTime(string value)
| >| {
| >| SetValue(value);
| >| }
| >| /// <summary>
| >| /// Constructor - initialise an
| >| OptionalDateTime to contain the value of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A DateTime value
| >| type.</param>
| >| public OptionalDateTime(DateTime value)
| >| {
| >| SetValue(value);
| >| }
| >| #endregion
| >|
| >| #region Public Methods
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a DateTime.
| >| /// </summary>
| >| /// <param name="value">A
| >| DateTime.</param>
| >| public void SetValue(DateTime value)
| >| {
| >| mDate = value;
| >| mIsNull = false;
| >| }
| >| /// <summary>
| >| /// Set the value of the object to equal
| >| that of a string. If the string is not a valid
| >| /// DateTime, the object is set to
| >| contain a null date.
| >| /// </summary>
| >| /// <param name="value">A string
| >| representing a valid date.</param>
| >| public void SetValue(string value)
| >| {
| >| if(value == null || value == "")
| >| {
| >| mIsNull = true;
| >| }
| >| else
| >| {
| >| try
| >| {
| >| mDate =
| >| DateTime.Parse(value);
| >| mIsNull = false;
| >| }
| >| catch
| >| {
| >| throw new
| >| ArgumentException("The string entered cannot be
| converted
| >| to a DateTime", "value");
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| string with optional formatting.
| >| /// </summary>
| >| /// <param name="Format">The format to
| >| return.</param>
| >| /// <returns>A string containing the
| >| correctly formatted date.</returns>
| >| public string GetValue(enumDateTimeFormat
| >| Format)
| >| {
| >| if(mIsNull)
| >| {
| >| return "";
| >| }
| >| else
| >| {
| >| switch(Format)
| >| {
| >| case
| >| enumDateTimeFormat.LongDateFormat:
| >| return
| >| mDate.ToLongDateString();
| >| case
| >| enumDateTimeFormat.LongTimeFormat:
| >| return
| >| mDate.ToLongTimeString();
| >| case
| >| enumDateTimeFormat.ShortDateFormat:
| >| return
| >| mDate.ToShortDateString();
| >| case
| >| enumDateTimeFormat.ShortTimeFormat:
| >| return
| >| mDate.ToShortTimeString();
| >| default:
| >| throw new
| >| UnhandledDateFormatException(Format);
| >| }
| >| }
| >| }
| >| /// <summary>
| >| /// Return the value of the object as a
| >| ShortDateString.
| >| /// </summary>
| >| /// <returns></returns>
| >| public string GetValue()
| >| {
| >| return GetValue
| >| (enumDateTimeFormat.ShortDateFormat);
| >| }
| >| #endregion
| >|
| >| #region Public Override Methods
| >| /// <summary>
| >| /// Passes a string containing the date
| >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| >| /// </summary>
| >| /// <returns>The date returned. Passes an
| >| empty string for blank (null) dates.</returns>
| >| public override string ToString()
| >| {
| >| return GetValue();
| >| }
| >| #endregion
| >|
| >| #region Properties
| >| /// <summary>
| >| /// Returns the date of the
| >| OptionalDateTime as a DateTime type. Raises the
| >| /// <see
| >| cref="OptionalDateTimeIsNullException"/> if the
| >| OptionalDateTime is
| >| /// blank (null). Check the <see
| >| cref="IsNull"/> property before calling this
| >| /// method to avoid the exception.
| >| /// </summary>
| >| public DateTime GetDateTime
| >| {
| >| get
| >| {
| >| if(mIsNull)
| >| {
| >| throw new
| >| OptionalDateTimeIsNullException();
| >| }
| >| return mDate;
| >| }
| >| }
| >| /// <summary>
| >| /// Gets a boolean value indicating
| >| whether the OptionalDateTime is blank (null).
| >| /// </summary>
| >| public bool IsNull
| >| {
| >| get
| >| {
| >| return mIsNull;
| >| }
| >| }
| >| #endregion
| >| }
| >|
| >| thanks in advance
| >|
| >
| >.
| >
|
 
J

Jeffrey Tan[MSFT]

Hi Guy,

Second way:

I found that the normal mouse click selection of DateTimePicker will fires
3 WM_NOTIFY messages which code are NM_RELEASECAPTURE, MCN_SELCHANGE,
MCN_SELECT. And if I filter MCN_SELCHANGE, MCN_SELECT message, the calendar
will not change its value. But the problem is if I filter these 2 message,
the Calendar will not fade away when I click a item. It will stay the
there. So we must kill it. I use P/invoke the Win32 API DestroyWindow to
get this done.

using System.Runtime .InteropServices ;

public bool readonlyval=false;
private DateTime oldval;

oldval=this.Value ; // in control's constructor

private const int MCN_FIRST=-750;
private const int MCN_SELCHANGE=MCN_FIRST + 1;
private const int MCN_SELECT=MCN_FIRST + 4;
private int WM_NOTIFY=0x004E;

[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hWnd1,IntPtr
hWnd2,string lpsz1,string lpsz2);

[DllImport("user32.dll")]
public static extern bool DestroyWindow(IntPtr hwnd);

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public int idfrom;
public int code;
}

protected override void WndProc(ref Message m)
{
if(this.readonlyval==true)
{
if(m.Msg==WM_NOTIFY)
{
if(m.HWnd==this.Handle)
{
NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
if(nm1.code==MCN_SELCHANGE)
{
return;
}
if(nm1.code ==MCN_SELECT)
{
IntPtr calendarhandle=FindWindowEx(IntPtr.Zero ,IntPtr.Zero
,"SysMonthCal32",String.Empty);
DestroyWindow(calendarhandle);
return;
}
}
}
}
base.WndProc (ref m);
}

Have a nice day!

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Newsgroups: microsoft.public.dotnet.languages.csharp
| From: (e-mail address removed) ("Jeffrey Tan[MSFT]")
| Organization: Microsoft
| Date: Wed, 29 Oct 2003 03:46:45 GMT
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| MIME-Version: 1.0
| Content-Type: text/plain
| Content-Transfer-Encoding: 7bit
|
|
| Hi Guy,
|
| Sorry for letting you waiting so long time.
| In this time, I did a lot of research into DateTimePicker control and
| wanted to find a workaround for you.
| Here, I provide you 2 ways of workaround:
| First: override its OnCloseUp method and reset its value to its original
| value. But this is not enough, when you open the datetimepicker, you can
| use keyboard arrow to navigate the selection, and the value displayed
will
| also change in the textbox( For the moment, we call it textbox). I think
we
| should not let this happen, the value should stay the same. But just
reset
| value in the OnValueChanged method seems work well on keyboard
navigation,
| but will again change the value when closing the calendar.(It seems that
| the OnCloseUp abated). So I hooked into this control, and filter its
| MCN_SELCHANGE notification in WM_NOTIFY message.
|
| using System.Runtime .InteropServices ;
| public bool readonlyval=false;
| private DateTime oldval;
|
| oldval=this.Value; // in this control's constructor
|
| protected override void OnCloseUp(EventArgs eventargs)
| {
| if(readonlyval==true)
| {
| this.Value =oldval;
| }
| oldval=this.Value ;
| base.OnCloseUp (eventargs);
| }
|
| private const int MCN_FIRST=-750;
| private const int MCN_SELCHANGE=MCN_FIRST + 1;
| private int WM_NOTIFY=0x004E;
|
| [StructLayout(LayoutKind.Sequential)]
| public struct NMHDR
| {
| public IntPtr hwndFrom;
| public int idfrom;
| public int code;
| }
|
| protected override void WndProc(ref Message m)
| {
| if(this.readonlyval==true)
| {
| if(m.Msg==WM_NOTIFY)
| {
| if(m.HWnd==this.Handle)
| {
| NMHDR nm1=(NMHDR)Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
| if(nm1.code==MCN_SELCHANGE)
| {
| return;
| }
| }
| }
| base.WndProc (ref m);
| }
| }
|
| I use Spy++ to find that the DateTimePicker control will receive
WM_NOTIFY
| message with MCN_SELCHANGE code when selection changes.
| All the const value MCN_SELCHANGE, MCN_FIRST can be found in the
C:\Program
| Files\Microsoft Visual Studio\VC98\Include directory *.h files.
|
| It works well on my machine. If you have any question, please feel free
to
| tell me.
| I will reply the second way of workaround in another reply post.
|
| Jeffrey Tan
| Microsoft Online Partner Support
| Get Secure! - www.microsoft.com/security
| This posting is provided "as is" with no warranties and confers no rights.
|
| --------------------
| | Content-Class: urn:content-classes:message
| | From: "guy" <[email protected]>
| | Sender: "guy" <[email protected]>
| | References: <[email protected]>
| <[email protected]>
| | Subject: RE: bug using Application.EnableVisualStyles() with
| datetimepicker control
| | Date: Tue, 28 Oct 2003 01:26:56 -0800
| | Lines: 601
| | Message-ID: <[email protected]>
| | MIME-Version: 1.0
| | Content-Type: text/plain;
| | charset="iso-8859-1"
| | Content-Transfer-Encoding: 7bit
| | X-Newsreader: Microsoft CDO for Windows 2000
| | Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| | X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| | Newsgroups: microsoft.public.dotnet.languages.csharp
| | Path: cpmsftngxa06.phx.gbl
| | Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.languages.csharp:194627
| | NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| | X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| |
| | Ok Jeffrey, ill wait for your reply
| |
| |
| |
| | >-----Original Message-----
| | >
| | >Hi Guy,
| | >
| | >It is an already known issue.
| | >I will do some research on this to find some workaround
| | for you.
| | >Thanks for you understanding.
| | >
| | >Best regards,
| | >Jeffrey Tan
| | >Microsoft Online Partner Support
| | >Get Secure! - www.microsoft.com/security
| | >This posting is provided "as is" with no warranties and
| | confers no rights.
| | >
| | >--------------------
| | >| Content-Class: urn:content-classes:message
| | >| From: "Guy" <[email protected]>
| | >| Sender: "Guy" <[email protected]>
| | >| Subject: bug using Application.EnableVisualStyles()
| | with datetimepicker
| | >control
| | >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| | >| Lines: 540
| | >| Message-ID: <[email protected]>
| | >| MIME-Version: 1.0
| | >| Content-Type: text/plain;
| | >| charset="iso-8859-1"
| | >| Content-Transfer-Encoding: 7bit
| | >| X-Newsreader: Microsoft CDO for Windows 2000
| | >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| | >| X-MimeOLE: Produced By Microsoft MimeOLE
| | V5.50.4910.0300
| | >| Newsgroups: microsoft.public.dotnet.languages.csharp
| | >| Path: cpmsftngxa06.phx.gbl
| | >| Xref: cpmsftngxa06.phx.gbl
| | microsoft.public.dotnet.languages.csharp:193774
| | >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| | >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| | >|
| | >| I have extended the datetimepicker control to
| | incorporate
| | >| a ReadOnly property.
| | >| I have used the new keyword to implement my own
| | version
| | >| of the value property, so that if readonly == true
| | then
| | >| it will not set the value of the control and will
| | leave
| | >| the checked status of the checkbox to false when a
| | user
| | >| selects a new date.
| | >|
| | >| this works fine when using the control on a win2k
| | machine
| | >| but if we use it on a win XP box and call
| | >| Application.EnableVisualStyles() then it seems to
| | ignore
| | >| my code and check the checkbox and set the value. this
| | is
| | >| extremely buggy behaviour! and also the value property
| | >| gets called twice (only once on a win2k box).
| | >|
| | >| i have also noticed behaviour changes in the
| | >| label.textalignment property when using XP Visual
| | styles
| | >| aswell. Below is my implementation of the extended
| | >| datetimepicker and also the new data type
| | >| (OptionalDateTime) that is used for the value
| | property...
| | >|
| | >| #####LockableDateTimePicker Source###########
| | >|
| | >| using System;
| | >| using System.Collections;
| | >| using System.ComponentModel;
| | >| using System.Drawing;
| | >| using System.Data;
| | >| using System.Windows.Forms;
| | >| using HCS.DataTypes;
| | >|
| | >| namespace HCS.Generic.UI.Controls
| | >| {
| | >| /// <summary>
| | >| /// LockableDateTimePicker is for selecting
| | >| dates. It manipulates the OptionalDateTime
| | >| /// class to allow null dates to be handled.
| | >| /// </summary>
| | >| public class LockableDateTimePicker :
| | >| DateTimePicker
| | >| {
| | >| #region Clean Up Code
| | >|
| | >| /// <summary>
| | >| /// Clean up any resources being used.
| | >| /// </summary>
| | >| protected override void Dispose( bool
| | >| disposing )
| | >| {
| | >| if( disposing )
| | >| {
| | >| if(components != null)
| | >| {
| | >| components.Dispose
| | >| ();
| | >| }
| | >| }
| | >| base.Dispose( disposing );
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Component Designer generated code
| | >| /// <summary>
| | >| /// Required method for Designer support -
| | >| do not modify
| | >| /// the contents of this method with the
| | >| code editor.
| | >| /// </summary>
| | >| private void InitializeComponent()
| | >| {
| | >| components = new
| | >| System.ComponentModel.Container();
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >|
| | >| private System.ComponentModel.Container
| | >| components = null;
| | >| private bool mReadOnly;
| | >| private DateTime mDateTime;
| | >| private Color mBackColor;
| | >| private Color mLockedColor;
| | >| private bool mChecked;
| | >|
| | >| #endregion
| | >|
| | >| #region Events
| | >|
| | >| public event OnReadOnlyChangedDelegate
| | >| OnReadOnlyChanged;
| | >|
| | >| #endregion
| | >|
| | >| #region EventArgs and Delegates
| | >|
| | >| public class OnReadOnlyChangedEventArgs :
| | >| EventArgs
| | >| {
| | >| private bool mReadOnly;
| | >|
| | >| public OnReadOnlyChangedEventArgs
| | >| (bool ReadOnly)
| | >| {
| | >| mReadOnly = ReadOnly;
| | >| }
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| }
| | >| }
| | >| public delegate void
| | >| OnReadOnlyChangedDelegate(object sender,
| | >| OnReadOnlyChangedEventArgs e);
| | >|
| | >| #endregion
| | >|
| | >| #region Constructor
| | >|
| | >| public LockableDateTimePicker()
| | >| {
| | >| // This call is required by the
| | >| Windows.Forms Form Designer.
| | >| InitializeComponent();
| | >|
| | >| mBackColor =
| | >| base.CalendarMonthBackground;
| | >| mLockedColor =
| | >| base.CalendarMonthBackground;
| | >|
| | >| //Set defaults for this control
| | >| base.Format =
| | >| DateTimePickerFormat.Short;
| | >|
| | >| //Make sure that our date backup
| | >| is populated
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Properties
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| set
| | >| {
| | >| if(value)
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mLockedColor;
| | >| }
| | >| else
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mBackColor;
| | >| }
| | >|
| | >| mReadOnly = value;
| | >| if(OnReadOnlyChanged !=
| | >| null)
| | >| {
| | >| OnReadOnlyChanged
| | >| (this, new OnReadOnlyChangedEventArgs(value));
| | >| }
| | >| }
| | >| }
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public Color LockedColor
| | >| {
| | >| get
| | >| {
| | >| return mLockedColor;
| | >| }
| | >| set
| | >| {
| | >| mLockedColor = value;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Overridden Properties
| | >| public override Color BackColor
| | >| {
| | >| get
| | >| {
| | >| return base.BackColor;
| | >| }
| | >| set
| | >| {
| | >| mBackColor = value;
| | >| if(!mReadOnly)
| | >| {
| | >| base.BackColor =
| | >| value;
| | >| }
| | >| }
| | >| }
| | >| public new OptionalDateTime Value
| | >| {
| | >| set
| | >| {
| | >| if(value.GetValue() == "")
| | >| {
| | >| base.Checked =
| | >| false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(value.GetValue());
| | >| }
| | >|
| | >| }
| | >| get
| | >| {
| | >| if(base.Checked)
| | >| {
| | >| return new
| | >| OptionalDateTime(base.Value);
| | >| }
| | >| else
| | >| {
| | >| return new
| | >| OptionalDateTime();
| | >| }
| | >| }
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Overridden Events
| | >|
| | >| protected override void OnValueChanged
| | >| (EventArgs eventargs)
| | >| {
| | >| base.OnValueChanged (eventargs);
| | >|
| | >| if(mReadOnly)
| | >| {
| | >| //We need to set the
| | >| value of the control back to
| | >| //the stored value, since
| | >| it is read only
| | >| if(base.Value !=
| | >| mDateTime)
| | >| {
| | >| base.Value =
| | >| mDateTime;
| | >| }
| | >| if(base.Checked !=
| | >| mChecked)
| | >| {
| | >| base.Checked =
| | >| mChecked;
| | >| }
| | >| }
| | >| else
| | >| {
| | >| //Store the value for
| | >| when it's read only
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| public void Initialise(OptionalDateTime
| | >| Value)
| | >| {
| | >| //Temporarily set the control to
| | >| not ReadOnly.
| | >| bool mTempReadOnly = mReadOnly;
| | >| if(mReadOnly)
| | >| {
| | >| mReadOnly = false;
| | >| }
| | >|
| | >| if(Value.GetValue() == "")
| | >| {
| | >| base.Checked = false;
| | >| mChecked = false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(Value.GetValue());
| | >| base.Checked = true;
| | >| mDateTime = base.Value;
| | >| mChecked = true;
| | >| }
| | >|
| | >| //Make sure the ReadOnly value is
| | >| returned to normal
| | >| mReadOnly = mTempReadOnly;
| | >| }
| | >| public void Initialise(DateTime Value)
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| (Value));
| | >| }
| | >| public void Initialise()
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| ());
| | >| }
| | >| #endregion
| | >| }
| | >| }
| | >|
| | >| ##############OptionalDateTime Source##########
| | >|
| | >| [Serializable()]
| | >| public class OptionalDateTime
| | >| {
| | >| #region Enum
| | >| /// <summary>
| | >| /// Formats available - extend as
| | >| required, but remember to update <see
| | cref="GetValue"/>.
| | >| /// </summary>
| | >| public enum enumDateTimeFormat
| | >| {
| | >| /// <summary>
| | >| /// LongDateFormat
| | >| /// </summary>
| | >| LongDateFormat,
| | >| /// <summary>
| | >| /// LongTimeFormat
| | >| /// </summary>
| | >| LongTimeFormat,
| | >| /// <summary>
| | >| /// ShortDateFormat
| | >| /// </summary>
| | >| ShortDateFormat,
| | >| /// <summary>
| | >| /// ShortTimeFormat
| | >| /// </summary>
| | >| ShortTimeFormat
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >| private DateTime mDate;
| | >| private bool mIsNull;
| | >| #endregion
| | >|
| | >| #region Constructor
| | >| /// <summary>
| | >| /// Constructor - initialises a null
| | >| OptionalDateTime
| | >| /// </summary>
| | >| public OptionalDateTime()
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a string.
| | >| /// If the string is not a valid
| | >| DateTime, the object is set to contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public OptionalDateTime(string value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A DateTime value
| | >| type.</param>
| | >| public OptionalDateTime(DateTime value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A
| | >| DateTime.</param>
| | >| public void SetValue(DateTime value)
| | >| {
| | >| mDate = value;
| | >| mIsNull = false;
| | >| }
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a string. If the string is not a valid
| | >| /// DateTime, the object is set to
| | >| contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public void SetValue(string value)
| | >| {
| | >| if(value == null || value == "")
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| else
| | >| {
| | >| try
| | >| {
| | >| mDate =
| | >| DateTime.Parse(value);
| | >| mIsNull = false;
| | >| }
| | >| catch
| | >| {
| | >| throw new
| | >| ArgumentException("The string entered cannot be
| | converted
| | >| to a DateTime", "value");
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| string with optional formatting.
| | >| /// </summary>
| | >| /// <param name="Format">The format to
| | >| return.</param>
| | >| /// <returns>A string containing the
| | >| correctly formatted date.</returns>
| | >| public string GetValue(enumDateTimeFormat
| | >| Format)
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| return "";
| | >| }
| | >| else
| | >| {
| | >| switch(Format)
| | >| {
| | >| case
| | >| enumDateTimeFormat.LongDateFormat:
| | >| return
| | >| mDate.ToLongDateString();
| | >| case
| | >| enumDateTimeFormat.LongTimeFormat:
| | >| return
| | >| mDate.ToLongTimeString();
| | >| case
| | >| enumDateTimeFormat.ShortDateFormat:
| | >| return
| | >| mDate.ToShortDateString();
| | >| case
| | >| enumDateTimeFormat.ShortTimeFormat:
| | >| return
| | >| mDate.ToShortTimeString();
| | >| default:
| | >| throw new
| | >| UnhandledDateFormatException(Format);
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| ShortDateString.
| | >| /// </summary>
| | >| /// <returns></returns>
| | >| public string GetValue()
| | >| {
| | >| return GetValue
| | >| (enumDateTimeFormat.ShortDateFormat);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Override Methods
| | >| /// <summary>
| | >| /// Passes a string containing the date
| | >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| | >| /// </summary>
| | >| /// <returns>The date returned. Passes an
| | >| empty string for blank (null) dates.</returns>
| | >| public override string ToString()
| | >| {
| | >| return GetValue();
| | >| }
| | >| #endregion
| | >|
| | >| #region Properties
| | >| /// <summary>
| | >| /// Returns the date of the
| | >| OptionalDateTime as a DateTime type. Raises the
| | >| /// <see
| | >| cref="OptionalDateTimeIsNullException"/> if the
| | >| OptionalDateTime is
| | >| /// blank (null). Check the <see
| | >| cref="IsNull"/> property before calling this
| | >| /// method to avoid the exception.
| | >| /// </summary>
| | >| public DateTime GetDateTime
| | >| {
| | >| get
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| throw new
| | >| OptionalDateTimeIsNullException();
| | >| }
| | >| return mDate;
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Gets a boolean value indicating
| | >| whether the OptionalDateTime is blank (null).
| | >| /// </summary>
| | >| public bool IsNull
| | >| {
| | >| get
| | >| {
| | >| return mIsNull;
| | >| }
| | >| }
| | >| #endregion
| | >| }
| | >|
| | >| thanks in advance
| | >|
| | >
| | >.
| | >
| |
|
 
G

Guy

Thanks Jeffrey,

there is some interesting stuff in the workarounds you
have given, hopefully the next version will be fixed
anyway!

Cheers

Guy


-----Original Message-----

Hi Guy,

Second way:

I found that the normal mouse click selection of DateTimePicker will fires
3 WM_NOTIFY messages which code are NM_RELEASECAPTURE, MCN_SELCHANGE,
MCN_SELECT. And if I filter MCN_SELCHANGE, MCN_SELECT message, the calendar
will not change its value. But the problem is if I filter these 2 message,
the Calendar will not fade away when I click a item. It will stay the
there. So we must kill it. I use P/invoke the Win32 API DestroyWindow to
get this done.

using System.Runtime .InteropServices ;

public bool readonlyval=false;
private DateTime oldval;

oldval=this.Value ; // in control's constructor

private const int MCN_FIRST=-750;
private const int MCN_SELCHANGE=MCN_FIRST + 1;
private const int MCN_SELECT=MCN_FIRST + 4;
private int WM_NOTIFY=0x004E;

[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hWnd1,IntPtr
hWnd2,string lpsz1,string lpsz2);

[DllImport("user32.dll")]
public static extern bool DestroyWindow(IntPtr hwnd);

[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public int idfrom;
public int code;
}

protected override void WndProc(ref Message m)
{
if(this.readonlyval==true)
{
if(m.Msg==WM_NOTIFY)
{
if(m.HWnd==this.Handle)
{
NMHDR nm1=(NMHDR) Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
(nm1.code==MCN_SELCHANGE)
{
return;
}
if(nm1.code ==MCN_SELECT)
{
IntPtr
calendarhandle=FindWindowEx(IntPtr.Zero ,IntPtr.Zero
,"SysMonthCal32",String.Empty);
DestroyWindow (calendarhandle);
return;
}
}
}
}
base.WndProc (ref m);
}

Have a nice day!

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Newsgroups: microsoft.public.dotnet.languages.csharp
| From: (e-mail address removed) ("Jeffrey Tan [MSFT]")
| Organization: Microsoft
| Date: Wed, 29 Oct 2003 03:46:45 GMT
| Subject: RE: bug using Application.EnableVisualStyles () with
datetimepicker control
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| MIME-Version: 1.0
| Content-Type: text/plain
| Content-Transfer-Encoding: 7bit
|
|
| Hi Guy,
|
| Sorry for letting you waiting so long time.
| In this time, I did a lot of research into DateTimePicker control and
| wanted to find a workaround for you.
| Here, I provide you 2 ways of workaround:
| First: override its OnCloseUp method and reset its value to its original
| value. But this is not enough, when you open the datetimepicker, you can
| use keyboard arrow to navigate the selection, and the value displayed
will
| also change in the textbox( For the moment, we call it textbox). I think
we
| should not let this happen, the value should stay the same. But just
reset
| value in the OnValueChanged method seems work well on keyboard
navigation,
| but will again change the value when closing the calendar.(It seems that
| the OnCloseUp abated). So I hooked into this control, and filter its
| MCN_SELCHANGE notification in WM_NOTIFY message.
|
| using System.Runtime .InteropServices ;
| public bool readonlyval=false;
| private DateTime oldval;
|
| oldval=this.Value; // in this control's constructor
|
| protected override void OnCloseUp(EventArgs eventargs)
| {
| if(readonlyval==true)
| {
| this.Value =oldval;
| }
| oldval=this.Value ;
| base.OnCloseUp (eventargs);
| }
|
| private const int MCN_FIRST=-750;
| private const int MCN_SELCHANGE=MCN_FIRST + 1;
| private int WM_NOTIFY=0x004E;
|
| [StructLayout(LayoutKind.Sequential)]
| public struct NMHDR
| {
| public IntPtr hwndFrom;
| public int idfrom;
| public int code;
| }
|
| protected override void WndProc(ref Message m)
| {
| if(this.readonlyval==true)
| {
| if(m.Msg==WM_NOTIFY)
| {
| if(m.HWnd==this.Handle)
| {
| NMHDR nm1=(NMHDR) Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
| if(nm1.code==MCN_SELCHANGE)
| {
| return;
| }
| }
| }
| base.WndProc (ref m);
| }
| }
|
| I use Spy++ to find that the DateTimePicker control will receive
WM_NOTIFY
| message with MCN_SELCHANGE code when selection changes.
| All the const value MCN_SELCHANGE, MCN_FIRST can be found in the
C:\Program
| Files\Microsoft Visual Studio\VC98\Include directory *.h files.
|
| It works well on my machine. If you have any question, please feel free
to
| tell me.
| I will reply the second way of workaround in another reply post.
|
| Jeffrey Tan
| Microsoft Online Partner Support
| Get Secure! - www.microsoft.com/security
| This posting is provided "as is" with no warranties and confers no rights.
|
| --------------------
| | Content-Class: urn:content-classes:message
| | From: "guy" <[email protected]>
| | Sender: "guy" <[email protected]>
| | References: <[email protected]>
| <[email protected]>
| | Subject: RE: bug using Application.EnableVisualStyles () with
| datetimepicker control
| | Date: Tue, 28 Oct 2003 01:26:56 -0800
| | Lines: 601
| | Message-ID: <[email protected]>
| | MIME-Version: 1.0
| | Content-Type: text/plain;
| | charset="iso-8859-1"
| | Content-Transfer-Encoding: 7bit
| | X-Newsreader: Microsoft CDO for Windows 2000
| | Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| | X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| | Newsgroups: microsoft.public.dotnet.languages.csharp
| | Path: cpmsftngxa06.phx.gbl
| | Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.languages.csharp:194627
| | NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| | X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| |
| | Ok Jeffrey, ill wait for your reply
| |
| |
| |
| | >-----Original Message-----
| | >
| | >Hi Guy,
| | >
| | >It is an already known issue.
| | >I will do some research on this to find some workaround
| | for you.
| | >Thanks for you understanding.
| | >
| | >Best regards,
| | >Jeffrey Tan
| | >Microsoft Online Partner Support
| | >Get Secure! - www.microsoft.com/security
| | >This posting is provided "as is" with no warranties and
| | confers no rights.
| | >
| | >--------------------
| | >| Content-Class: urn:content-classes:message
| | >| From: "Guy" <[email protected]>
| | >| Sender: "Guy" <[email protected]>
| | >| Subject: bug using Application.EnableVisualStyles ()
| | with datetimepicker
| | >control
| | >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| | >| Lines: 540
| | >| Message-ID: <085401c39a1d$7c2d0480 [email protected]>
| | >| MIME-Version: 1.0
| | >| Content-Type: text/plain;
| | >| charset="iso-8859-1"
| | >| Content-Transfer-Encoding: 7bit
| | >| X-Newsreader: Microsoft CDO for Windows 2000
| | >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| | >| X-MimeOLE: Produced By Microsoft MimeOLE
| | V5.50.4910.0300
| | >| Newsgroups: microsoft.public.dotnet.languages.csharp
| | >| Path: cpmsftngxa06.phx.gbl
| | >| Xref: cpmsftngxa06.phx.gbl
| | microsoft.public.dotnet.languages.csharp:193774
| | >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| | >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| | >|
| | >| I have extended the datetimepicker control to
| | incorporate
| | >| a ReadOnly property.
| | >| I have used the new keyword to implement my own
| | version
| | >| of the value property, so that if readonly == true
| | then
| | >| it will not set the value of the control and will
| | leave
| | >| the checked status of the checkbox to false when a
| | user
| | >| selects a new date.
| | >|
| | >| this works fine when using the control on a win2k
| | machine
| | >| but if we use it on a win XP box and call
| | >| Application.EnableVisualStyles() then it seems to
| | ignore
| | >| my code and check the checkbox and set the value. this
| | is
| | >| extremely buggy behaviour! and also the value property
| | >| gets called twice (only once on a win2k box).
| | >|
| | >| i have also noticed behaviour changes in the
| | >| label.textalignment property when using XP Visual
| | styles
| | >| aswell. Below is my implementation of the extended
| | >| datetimepicker and also the new data type
| | >| (OptionalDateTime) that is used for the value
| | property...
| | >|
| | >| #####LockableDateTimePicker Source###########
| | >|
| | >| using System;
| | >| using System.Collections;
| | >| using System.ComponentModel;
| | >| using System.Drawing;
| | >| using System.Data;
| | >| using System.Windows.Forms;
| | >| using HCS.DataTypes;
| | >|
| | >| namespace HCS.Generic.UI.Controls
| | >| {
| | >| /// <summary>
| | >| /// LockableDateTimePicker is for selecting
| | >| dates. It manipulates the OptionalDateTime
| | >| /// class to allow null dates to be handled.
| | >| /// </summary>
| | >| public class LockableDateTimePicker :
| | >| DateTimePicker
| | >| {
| | >| #region Clean Up Code
| | >|
| | >| /// <summary>
| | >| /// Clean up any resources being used.
| | >| /// </summary>
| | >| protected override void Dispose( bool
| | >| disposing )
| | >| {
| | >| if( disposing )
| | >| {
| | >| if(components != null)
| | >| {
| | >| components.Dispose
| | >| ();
| | >| }
| | >| }
| | >| base.Dispose( disposing );
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Component Designer generated code
| | >| /// <summary>
| | >| /// Required method for Designer support -
| | >| do not modify
| | >| /// the contents of this method with the
| | >| code editor.
| | >| /// </summary>
| | >| private void InitializeComponent()
| | >| {
| | >| components = new
| | >| System.ComponentModel.Container();
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >|
| | >| private System.ComponentModel.Container
| | >| components = null;
| | >| private bool mReadOnly;
| | >| private DateTime mDateTime;
| | >| private Color mBackColor;
| | >| private Color mLockedColor;
| | >| private bool mChecked;
| | >|
| | >| #endregion
| | >|
| | >| #region Events
| | >|
| | >| public event OnReadOnlyChangedDelegate
| | >| OnReadOnlyChanged;
| | >|
| | >| #endregion
| | >|
| | >| #region EventArgs and Delegates
| | >|
| | >| public class OnReadOnlyChangedEventArgs :
| | >| EventArgs
| | >| {
| | >| private bool mReadOnly;
| | >|
| | >| public OnReadOnlyChangedEventArgs
| | >| (bool ReadOnly)
| | >| {
| | >| mReadOnly = ReadOnly;
| | >| }
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| }
| | >| }
| | >| public delegate void
| | >| OnReadOnlyChangedDelegate(object sender,
| | >| OnReadOnlyChangedEventArgs e);
| | >|
| | >| #endregion
| | >|
| | >| #region Constructor
| | >|
| | >| public LockableDateTimePicker()
| | >| {
| | >| // This call is required by the
| | >| Windows.Forms Form Designer.
| | >| InitializeComponent();
| | >|
| | >| mBackColor =
| | >| base.CalendarMonthBackground;
| | >| mLockedColor =
| | >| base.CalendarMonthBackground;
| | >|
| | >| //Set defaults for this control
| | >| base.Format =
| | >| DateTimePickerFormat.Short;
| | >|
| | >| //Make sure that our date backup
| | >| is populated
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Properties
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public bool ReadOnly
| | >| {
| | >| get
| | >| {
| | >| return mReadOnly;
| | >| }
| | >| set
| | >| {
| | >| if(value)
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mLockedColor;
| | >| }
| | >| else
| | >| {
| | >|
| | >| base.CalendarMonthBackground = mBackColor;
| | >| }
| | >|
| | >| mReadOnly = value;
| | >| if (OnReadOnlyChanged !=
| | >| null)
| | >| {
| | >| OnReadOnlyChanged
| | >| (this, new OnReadOnlyChangedEventArgs(value));
| | >| }
| | >| }
| | >| }
| | >|
| | >| [DesignerSerializationVisibility
| | >| (DesignerSerializationVisibility.Visible)]
| | >| public Color LockedColor
| | >| {
| | >| get
| | >| {
| | >| return mLockedColor;
| | >| }
| | >| set
| | >| {
| | >| mLockedColor = value;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Overridden Properties
| | >| public override Color BackColor
| | >| {
| | >| get
| | >| {
| | >| return base.BackColor;
| | >| }
| | >| set
| | >| {
| | >| mBackColor = value;
| | >| if(!mReadOnly)
| | >| {
| | >| base.BackColor =
| | >| value;
| | >| }
| | >| }
| | >| }
| | >| public new OptionalDateTime Value
| | >| {
| | >| set
| | >| {
| | >| if(value.GetValue () == "")
| | >| {
| | >| base.Checked =
| | >| false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(value.GetValue());
| | >| }
| | >|
| | >| }
| | >| get
| | >| {
| | >| if(base.Checked)
| | >| {
| | >| return new
| | >| OptionalDateTime(base.Value);
| | >| }
| | >| else
| | >| {
| | >| return new
| | >| OptionalDateTime();
| | >| }
| | >| }
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Overridden Events
| | >|
| | >| protected override void OnValueChanged
| | >| (EventArgs eventargs)
| | >| {
| | >| base.OnValueChanged (eventargs);
| | >|
| | >| if(mReadOnly)
| | >| {
| | >| //We need to set the
| | >| value of the control back to
| | >| //the stored value, since
| | >| it is read only
| | >| if(base.Value !=
| | >| mDateTime)
| | >| {
| | >| base.Value =
| | >| mDateTime;
| | >| }
| | >| if(base.Checked ! =
| | >| mChecked)
| | >| {
| | >| base.Checked =
| | >| mChecked;
| | >| }
| | >| }
| | >| else
| | >| {
| | >| //Store the value for
| | >| when it's read only
| | >| mDateTime = base.Value;
| | >| mChecked = base.Checked;
| | >| }
| | >| }
| | >|
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| public void Initialise (OptionalDateTime
| | >| Value)
| | >| {
| | >| //Temporarily set the control to
| | >| not ReadOnly.
| | >| bool mTempReadOnly = mReadOnly;
| | >| if(mReadOnly)
| | >| {
| | >| mReadOnly = false;
| | >| }
| | >|
| | >| if(Value.GetValue() == "")
| | >| {
| | >| base.Checked = false;
| | >| mChecked = false;
| | >| }
| | >| else
| | >| {
| | >| base.Value =
| | >| DateTime.Parse(Value.GetValue());
| | >| base.Checked = true;
| | >| mDateTime = base.Value;
| | >| mChecked = true;
| | >| }
| | >|
| | >| //Make sure the ReadOnly value is
| | >| returned to normal
| | >| mReadOnly = mTempReadOnly;
| | >| }
| | >| public void Initialise(DateTime Value)
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| (Value));
| | >| }
| | >| public void Initialise()
| | >| {
| | >| Initialise(new OptionalDateTime
| | >| ());
| | >| }
| | >| #endregion
| | >| }
| | >| }
| | >|
| | >| ##############OptionalDateTime Source##########
| | >|
| | >| [Serializable()]
| | >| public class OptionalDateTime
| | >| {
| | >| #region Enum
| | >| /// <summary>
| | >| /// Formats available - extend as
| | >| required, but remember to update <see
| | cref="GetValue"/>.
| | >| /// </summary>
| | >| public enum enumDateTimeFormat
| | >| {
| | >| /// <summary>
| | >| /// LongDateFormat
| | >| /// </summary>
| | >| LongDateFormat,
| | >| /// <summary>
| | >| /// LongTimeFormat
| | >| /// </summary>
| | >| LongTimeFormat,
| | >| /// <summary>
| | >| /// ShortDateFormat
| | >| /// </summary>
| | >| ShortDateFormat,
| | >| /// <summary>
| | >| /// ShortTimeFormat
| | >| /// </summary>
| | >| ShortTimeFormat
| | >| }
| | >| #endregion
| | >|
| | >| #region Fields
| | >| private DateTime mDate;
| | >| private bool mIsNull;
| | >| #endregion
| | >|
| | >| #region Constructor
| | >| /// <summary>
| | >| /// Constructor - initialises a null
| | >| OptionalDateTime
| | >| /// </summary>
| | >| public OptionalDateTime()
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a string.
| | >| /// If the string is not a valid
| | >| DateTime, the object is set to contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public OptionalDateTime(string value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| /// <summary>
| | >| /// Constructor - initialise an
| | >| OptionalDateTime to contain the value of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A DateTime value
| | >| type.</param>
| | >| public OptionalDateTime(DateTime value)
| | >| {
| | >| SetValue(value);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Methods
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a DateTime.
| | >| /// </summary>
| | >| /// <param name="value">A
| | >| DateTime.</param>
| | >| public void SetValue(DateTime value)
| | >| {
| | >| mDate = value;
| | >| mIsNull = false;
| | >| }
| | >| /// <summary>
| | >| /// Set the value of the object to equal
| | >| that of a string. If the string is not a valid
| | >| /// DateTime, the object is set to
| | >| contain a null date.
| | >| /// </summary>
| | >| /// <param name="value">A string
| | >| representing a valid date.</param>
| | >| public void SetValue(string value)
| | >| {
| | >| if(value == null || value == "")
| | >| {
| | >| mIsNull = true;
| | >| }
| | >| else
| | >| {
| | >| try
| | >| {
| | >| mDate =
| | >| DateTime.Parse(value);
| | >| mIsNull = false;
| | >| }
| | >| catch
| | >| {
| | >| throw new
| | >| ArgumentException("The string entered cannot be
| | converted
| | >| to a DateTime", "value");
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| string with optional formatting.
| | >| /// </summary>
| | >| /// <param name="Format">The format to
| | >| return.</param>
| | >| /// <returns>A string containing the
| | >| correctly formatted date.</returns>
| | >| public string GetValue (enumDateTimeFormat
| | >| Format)
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| return "";
| | >| }
| | >| else
| | >| {
| | >| switch(Format)
| | >| {
| | >| case
| | >| enumDateTimeFormat.LongDateFormat:
| | >| return
| | >| mDate.ToLongDateString();
| | >| case
| | >| enumDateTimeFormat.LongTimeFormat:
| | >| return
| | >| mDate.ToLongTimeString();
| | >| case
| | >| enumDateTimeFormat.ShortDateFormat:
| | >| return
| | >| mDate.ToShortDateString();
| | >| case
| | >| enumDateTimeFormat.ShortTimeFormat:
| | >| return
| | >| mDate.ToShortTimeString();
| | >| default:
| | >| throw new
| | >| UnhandledDateFormatException(Format);
| | >| }
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Return the value of the object as a
| | >| ShortDateString.
| | >| /// </summary>
| | >| /// <returns></returns>
| | >| public string GetValue()
| | >| {
| | >| return GetValue
| | >| (enumDateTimeFormat.ShortDateFormat);
| | >| }
| | >| #endregion
| | >|
| | >| #region Public Override Methods
| | >| /// <summary>
| | >| /// Passes a string containing the date
| | >| in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
| | >| /// </summary>
| | >| /// <returns>The date returned. Passes an
| | >| empty string for blank (null) dates.</returns>
| | >| public override string ToString()
| | >| {
| | >| return GetValue();
| | >| }
| | >| #endregion
| | >|
| | >| #region Properties
| | >| /// <summary>
| | >| /// Returns the date of the
| | >| OptionalDateTime as a DateTime type. Raises the
| | >| /// <see
| | >| cref="OptionalDateTimeIsNullException"/> if the
| | >| OptionalDateTime is
| | >| /// blank (null). Check the <see
| | >| cref="IsNull"/> property before calling this
| | >| /// method to avoid the exception.
| | >| /// </summary>
| | >| public DateTime GetDateTime
| | >| {
| | >| get
| | >| {
| | >| if(mIsNull)
| | >| {
| | >| throw new
| | >| OptionalDateTimeIsNullException();
| | >| }
| | >| return mDate;
| | >| }
| | >| }
| | >| /// <summary>
| | >| /// Gets a boolean value indicating
| | >| whether the OptionalDateTime is blank (null).
| | >| /// </summary>
| | >| public bool IsNull
| | >| {
| | >| get
| | >| {
| | >| return mIsNull;
| | >| }
| | >| }
| | >| #endregion
| | >| }
| | >|
| | >| thanks in advance
| | >|
| | >
| | >.
| | >
| |
|

.
 
J

Jeffrey Tan[MSFT]

Hi Guy,

I am glad my workaround makes sense to you.
We have recognized this issue, and registered this issue in our document.
Thanks for your suggestion.
Have a nice day!

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "Guy" <[email protected]>
| Sender: "Guy" <[email protected]>
| References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
| Subject: RE: bug using Application.EnableVisualStyles() with
datetimepicker control
| Date: Wed, 29 Oct 2003 07:25:20 -0800
| Lines: 936
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOeMN0MVnak9MhtTgyiX4kq1GG8Qw==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:195079
| NNTP-Posting-Host: TK2MSFTNGXA09 10.40.1.161
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Thanks Jeffrey,
|
| there is some interesting stuff in the workarounds you
| have given, hopefully the next version will be fixed
| anyway!
|
| Cheers
|
| Guy
|
|
|
| >-----Original Message-----
| >
| >Hi Guy,
| >
| >Second way:
| >
| >I found that the normal mouse click selection of
| DateTimePicker will fires
| >3 WM_NOTIFY messages which code are NM_RELEASECAPTURE,
| MCN_SELCHANGE,
| >MCN_SELECT. And if I filter MCN_SELCHANGE, MCN_SELECT
| message, the calendar
| >will not change its value. But the problem is if I
| filter these 2 message,
| >the Calendar will not fade away when I click a item. It
| will stay the
| >there. So we must kill it. I use P/invoke the Win32 API
| DestroyWindow to
| >get this done.
| >
| >using System.Runtime .InteropServices ;
| >
| >public bool readonlyval=false;
| >private DateTime oldval;
| >
| >oldval=this.Value ; // in control's constructor
| >
| >private const int MCN_FIRST=-750;
| >private const int MCN_SELCHANGE=MCN_FIRST + 1;
| >private const int MCN_SELECT=MCN_FIRST + 4;
| >private int WM_NOTIFY=0x004E;
| >
| >[DllImport("user32.dll")]
| >public static extern IntPtr FindWindowEx(IntPtr
| hWnd1,IntPtr
| >hWnd2,string lpsz1,string lpsz2);
| >
| >[DllImport("user32.dll")]
| >public static extern bool DestroyWindow(IntPtr hwnd);
| >
| >[StructLayout(LayoutKind.Sequential)]
| > public struct NMHDR
| >{
| > public IntPtr hwndFrom;
| > public int idfrom;
| > public int code;
| >}
| >
| >protected override void WndProc(ref Message m)
| >{
| > if(this.readonlyval==true)
| > {
| > if(m.Msg==WM_NOTIFY)
| > {
| > if(m.HWnd==this.Handle)
| > {
| > NMHDR nm1=(NMHDR)
| Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
| > if
| (nm1.code==MCN_SELCHANGE)
| > {
| > return;
| > }
| > if(nm1.code ==MCN_SELECT)
| > {
| > IntPtr
| calendarhandle=FindWindowEx(IntPtr.Zero ,IntPtr.Zero
| >,"SysMonthCal32",String.Empty);
| > DestroyWindow
| (calendarhandle);
| > return;
| > }
| > }
| > }
| > }
| > base.WndProc (ref m);
| >}
| >
| >Have a nice day!
| >
| >Best regards,
| >Jeffrey Tan
| >Microsoft Online Partner Support
| >Get Secure! - www.microsoft.com/security
| >This posting is provided "as is" with no warranties and
| confers no rights.
| >
| >--------------------
| >| Newsgroups: microsoft.public.dotnet.languages.csharp
| >| From: (e-mail address removed) ("Jeffrey Tan
| [MSFT]")
| >| Organization: Microsoft
| >| Date: Wed, 29 Oct 2003 03:46:45 GMT
| >| Subject: RE: bug using Application.EnableVisualStyles
| () with
| >datetimepicker control
| >| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| >| MIME-Version: 1.0
| >| Content-Type: text/plain
| >| Content-Transfer-Encoding: 7bit
| >|
| >|
| >| Hi Guy,
| >|
| >| Sorry for letting you waiting so long time.
| >| In this time, I did a lot of research into
| DateTimePicker control and
| >| wanted to find a workaround for you.
| >| Here, I provide you 2 ways of workaround:
| >| First: override its OnCloseUp method and reset its
| value to its original
| >| value. But this is not enough, when you open the
| datetimepicker, you can
| >| use keyboard arrow to navigate the selection, and the
| value displayed
| >will
| >| also change in the textbox( For the moment, we call it
| textbox). I think
| >we
| >| should not let this happen, the value should stay the
| same. But just
| >reset
| >| value in the OnValueChanged method seems work well on
| keyboard
| >navigation,
| >| but will again change the value when closing the
| calendar.(It seems that
| >| the OnCloseUp abated). So I hooked into this control,
| and filter its
| >| MCN_SELCHANGE notification in WM_NOTIFY message.
| >|
| >| using System.Runtime .InteropServices ;
| >| public bool readonlyval=false;
| >| private DateTime oldval;
| >|
| >| oldval=this.Value; // in this control's constructor
| >|
| >| protected override void OnCloseUp(EventArgs eventargs)
| >| {
| >| if(readonlyval==true)
| >| {
| >| this.Value =oldval;
| >| }
| >| oldval=this.Value ;
| >| base.OnCloseUp (eventargs);
| >| }
| >|
| >| private const int MCN_FIRST=-750;
| >| private const int MCN_SELCHANGE=MCN_FIRST + 1;
| >| private int WM_NOTIFY=0x004E;
| >|
| >| [StructLayout(LayoutKind.Sequential)]
| >| public struct NMHDR
| >| {
| >| public IntPtr hwndFrom;
| >| public int idfrom;
| >| public int code;
| >| }
| >|
| >| protected override void WndProc(ref Message m)
| >| {
| >| if(this.readonlyval==true)
| >| {
| >| if(m.Msg==WM_NOTIFY)
| >| {
| >| if(m.HWnd==this.Handle)
| >| {
| >| NMHDR nm1=(NMHDR)
| Marshal.PtrToStructure(m.LParam,typeof(NMHDR));
| >| if(nm1.code==MCN_SELCHANGE)
| >| {
| >| return;
| >| }
| >| }
| >| }
| >| base.WndProc (ref m);
| >| }
| >| }
| >|
| >| I use Spy++ to find that the DateTimePicker control
| will receive
| >WM_NOTIFY
| >| message with MCN_SELCHANGE code when selection changes.
| >| All the const value MCN_SELCHANGE, MCN_FIRST can be
| found in the
| >C:\Program
| >| Files\Microsoft Visual Studio\VC98\Include directory
| *.h files.
| >|
| >| It works well on my machine. If you have any question,
| please feel free
| >to
| >| tell me.
| >| I will reply the second way of workaround in another
| reply post.
| >|
| >| Jeffrey Tan
| >| Microsoft Online Partner Support
| >| Get Secure! - www.microsoft.com/security
| >| This posting is provided "as is" with no warranties
| and confers no rights.
| >|
| >| --------------------
| >| | Content-Class: urn:content-classes:message
| >| | From: "guy" <[email protected]>
| >| | Sender: "guy" <[email protected]>
| >| | References: <[email protected]>
| >| <[email protected]>
| >| | Subject: RE: bug using Application.EnableVisualStyles
| () with
| >| datetimepicker control
| >| | Date: Tue, 28 Oct 2003 01:26:56 -0800
| >| | Lines: 601
| >| | Message-ID: <[email protected]>
| >| | MIME-Version: 1.0
| >| | Content-Type: text/plain;
| >| | charset="iso-8859-1"
| >| | Content-Transfer-Encoding: 7bit
| >| | X-Newsreader: Microsoft CDO for Windows 2000
| >| | Thread-Index: AcOdNaFMO+yabmhBTea+z5L0ii9kXg==
| >| | X-MimeOLE: Produced By Microsoft MimeOLE
| V5.50.4910.0300
| >| | Newsgroups: microsoft.public.dotnet.languages.csharp
| >| | Path: cpmsftngxa06.phx.gbl
| >| | Xref: cpmsftngxa06.phx.gbl
| >microsoft.public.dotnet.languages.csharp:194627
| >| | NNTP-Posting-Host: TK2MSFTNGXA14 10.40.1.166
| >| | X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| >| |
| >| | Ok Jeffrey, ill wait for your reply
| >| |
| >| |
| >| |
| >| | >-----Original Message-----
| >| | >
| >| | >Hi Guy,
| >| | >
| >| | >It is an already known issue.
| >| | >I will do some research on this to find some
| workaround
| >| | for you.
| >| | >Thanks for you understanding.
| >| | >
| >| | >Best regards,
| >| | >Jeffrey Tan
| >| | >Microsoft Online Partner Support
| >| | >Get Secure! - www.microsoft.com/security
| >| | >This posting is provided "as is" with no warranties
| and
| >| | confers no rights.
| >| | >
| >| | >--------------------
| >| | >| Content-Class: urn:content-classes:message
| >| | >| From: "Guy" <[email protected]>
| >| | >| Sender: "Guy" <[email protected]>
| >| | >| Subject: bug using Application.EnableVisualStyles
| ()
| >| | with datetimepicker
| >| | >control
| >| | >| Date: Fri, 24 Oct 2003 03:56:32 -0700
| >| | >| Lines: 540
| >| | >| Message-ID: <085401c39a1d$7c2d0480
| [email protected]>
| >| | >| MIME-Version: 1.0
| >| | >| Content-Type: text/plain;
| >| | >| charset="iso-8859-1"
| >| | >| Content-Transfer-Encoding: 7bit
| >| | >| X-Newsreader: Microsoft CDO for Windows 2000
| >| | >| Thread-Index: AcOaHXwtoiMaL/QOSWuDQUgjMGLnAw==
| >| | >| X-MimeOLE: Produced By Microsoft MimeOLE
| >| | V5.50.4910.0300
| >| | >| Newsgroups:
| microsoft.public.dotnet.languages.csharp
| >| | >| Path: cpmsftngxa06.phx.gbl
| >| | >| Xref: cpmsftngxa06.phx.gbl
| >| | microsoft.public.dotnet.languages.csharp:193774
| >| | >| NNTP-Posting-Host: TK2MSFTNGXA13 10.40.1.165
| >| | >| X-Tomcat-NG:
| microsoft.public.dotnet.languages.csharp
| >| | >|
| >| | >| I have extended the datetimepicker control to
| >| | incorporate
| >| | >| a ReadOnly property.
| >| | >| I have used the new keyword to implement my own
| >| | version
| >| | >| of the value property, so that if readonly ==
| true
| >| | then
| >| | >| it will not set the value of the control and will
| >| | leave
| >| | >| the checked status of the checkbox to false when
| a
| >| | user
| >| | >| selects a new date.
| >| | >|
| >| | >| this works fine when using the control on a win2k
| >| | machine
| >| | >| but if we use it on a win XP box and call
| >| | >| Application.EnableVisualStyles() then it seems to
| >| | ignore
| >| | >| my code and check the checkbox and set the value.
| this
| >| | is
| >| | >| extremely buggy behaviour! and also the value
| property
| >| | >| gets called twice (only once on a win2k box).
| >| | >|
| >| | >| i have also noticed behaviour changes in the
| >| | >| label.textalignment property when using XP Visual
| >| | styles
| >| | >| aswell. Below is my implementation of the
| extended
| >| | >| datetimepicker and also the new data type
| >| | >| (OptionalDateTime) that is used for the value
| >| | property...
| >| | >|
| >| | >| #####LockableDateTimePicker Source###########
| >| | >|
| >| | >| using System;
| >| | >| using System.Collections;
| >| | >| using System.ComponentModel;
| >| | >| using System.Drawing;
| >| | >| using System.Data;
| >| | >| using System.Windows.Forms;
| >| | >| using HCS.DataTypes;
| >| | >|
| >| | >| namespace HCS.Generic.UI.Controls
| >| | >| {
| >| | >| /// <summary>
| >| | >| /// LockableDateTimePicker is for
| selecting
| >| | >| dates. It manipulates the OptionalDateTime
| >| | >| /// class to allow null dates to be
| handled.
| >| | >| /// </summary>
| >| | >| public class LockableDateTimePicker :
| >| | >| DateTimePicker
| >| | >| {
| >| | >| #region Clean Up Code
| >| | >|
| >| | >| /// <summary>
| >| | >| /// Clean up any resources being
| used.
| >| | >| /// </summary>
| >| | >| protected override void Dispose(
| bool
| >| | >| disposing )
| >| | >| {
| >| | >| if( disposing )
| >| | >| {
| >| | >| if(components !=
| null)
| >| | >| {
| >| | >|
| components.Dispose
| >| | >| ();
| >| | >| }
| >| | >| }
| >| | >| base.Dispose( disposing );
| >| | >| }
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Component Designer
| generated code
| >| | >| /// <summary>
| >| | >| /// Required method for Designer
| support -
| >| | >| do not modify
| >| | >| /// the contents of this method
| with the
| >| | >| code editor.
| >| | >| /// </summary>
| >| | >| private void InitializeComponent()
| >| | >| {
| >| | >| components = new
| >| | >| System.ComponentModel.Container();
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Fields
| >| | >|
| >| | >| private
| System.ComponentModel.Container
| >| | >| components = null;
| >| | >| private bool mReadOnly;
| >| | >| private DateTime mDateTime;
| >| | >| private Color mBackColor;
| >| | >| private Color mLockedColor;
| >| | >| private bool mChecked;
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Events
| >| | >|
| >| | >| public event
| OnReadOnlyChangedDelegate
| >| | >| OnReadOnlyChanged;
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region EventArgs and Delegates
| >| | >|
| >| | >| public class
| OnReadOnlyChangedEventArgs :
| >| | >| EventArgs
| >| | >| {
| >| | >| private bool mReadOnly;
| >| | >|
| >| | >| public
| OnReadOnlyChangedEventArgs
| >| | >| (bool ReadOnly)
| >| | >| {
| >| | >| mReadOnly =
| ReadOnly;
| >| | >| }
| >| | >| public bool ReadOnly
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| return
| mReadOnly;
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >| public delegate void
| >| | >| OnReadOnlyChangedDelegate(object sender,
| >| | >| OnReadOnlyChangedEventArgs e);
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Constructor
| >| | >|
| >| | >| public LockableDateTimePicker()
| >| | >| {
| >| | >| // This call is required
| by the
| >| | >| Windows.Forms Form Designer.
| >| | >| InitializeComponent();
| >| | >|
| >| | >| mBackColor =
| >| | >| base.CalendarMonthBackground;
| >| | >| mLockedColor =
| >| | >| base.CalendarMonthBackground;
| >| | >|
| >| | >| //Set defaults for this
| control
| >| | >| base.Format =
| >| | >| DateTimePickerFormat.Short;
| >| | >|
| >| | >| //Make sure that our date
| backup
| >| | >| is populated
| >| | >| mDateTime = base.Value;
| >| | >| mChecked = base.Checked;
| >| | >| }
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Properties
| >| | >|
| >| | >| [DesignerSerializationVisibility
| >| | >| (DesignerSerializationVisibility.Visible)]
| >| | >| public bool ReadOnly
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| return mReadOnly;
| >| | >| }
| >| | >| set
| >| | >| {
| >| | >| if(value)
| >| | >| {
| >| | >|
| >| | >| base.CalendarMonthBackground =
| mLockedColor;
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >|
| >| | >| base.CalendarMonthBackground = mBackColor;
| >| | >| }
| >| | >|
| >| | >| mReadOnly = value;
| >| | >| if
| (OnReadOnlyChanged !=
| >| | >| null)
| >| | >| {
| >| | >|
| OnReadOnlyChanged
| >| | >| (this, new OnReadOnlyChangedEventArgs(value));
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >|
| >| | >| [DesignerSerializationVisibility
| >| | >| (DesignerSerializationVisibility.Visible)]
| >| | >| public Color LockedColor
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| return
| mLockedColor;
| >| | >| }
| >| | >| set
| >| | >| {
| >| | >| mLockedColor =
| value;
| >| | >| }
| >| | >| }
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Public Overridden
| Properties
| >| | >| public override Color BackColor
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| return
| base.BackColor;
| >| | >| }
| >| | >| set
| >| | >| {
| >| | >| mBackColor =
| value;
| >| | >| if(!mReadOnly)
| >| | >| {
| >| | >|
| base.BackColor =
| >| | >| value;
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >| public new OptionalDateTime Value
| >| | >| {
| >| | >| set
| >| | >| {
| >| | >| if(value.GetValue
| () == "")
| >| | >| {
| >| | >|
| base.Checked =
| >| | >| false;
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >|
| base.Value =
| >| | >| DateTime.Parse(value.GetValue());
| >| | >| }
| >| | >|
| >| | >| }
| >| | >| get
| >| | >| {
| >| | >| if(base.Checked)
| >| | >| {
| >| | >| return
| new
| >| | >| OptionalDateTime(base.Value);
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >| return
| new
| >| | >| OptionalDateTime();
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Public Overridden Events
| >| | >|
| >| | >| protected override void
| OnValueChanged
| >| | >| (EventArgs eventargs)
| >| | >| {
| >| | >| base.OnValueChanged
| (eventargs);
| >| | >|
| >| | >| if(mReadOnly)
| >| | >| {
| >| | >| //We need to set
| the
| >| | >| value of the control back to
| >| | >| //the stored
| value, since
| >| | >| it is read only
| >| | >| if(base.Value !=
| >| | >| mDateTime)
| >| | >| {
| >| | >|
| base.Value =
| >| | >| mDateTime;
| >| | >| }
| >| | >| if(base.Checked !
| =
| >| | >| mChecked)
| >| | >| {
| >| | >|
| base.Checked =
| >| | >| mChecked;
| >| | >| }
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >| //Store the value
| for
| >| | >| when it's read only
| >| | >| mDateTime =
| base.Value;
| >| | >| mChecked =
| base.Checked;
| >| | >| }
| >| | >| }
| >| | >|
| >| | >| #endregion
| >| | >|
| >| | >| #region Public Methods
| >| | >| public void Initialise
| (OptionalDateTime
| >| | >| Value)
| >| | >| {
| >| | >| //Temporarily set the
| control to
| >| | >| not ReadOnly.
| >| | >| bool mTempReadOnly =
| mReadOnly;
| >| | >| if(mReadOnly)
| >| | >| {
| >| | >| mReadOnly = false;
| >| | >| }
| >| | >|
| >| | >| if(Value.GetValue() == "")
| >| | >| {
| >| | >| base.Checked =
| false;
| >| | >| mChecked = false;
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >| base.Value =
| >| | >| DateTime.Parse(Value.GetValue());
| >| | >| base.Checked =
| true;
| >| | >| mDateTime =
| base.Value;
| >| | >| mChecked = true;
| >| | >| }
| >| | >|
| >| | >| //Make sure the ReadOnly
| value is
| >| | >| returned to normal
| >| | >| mReadOnly = mTempReadOnly;
| >| | >| }
| >| | >| public void Initialise(DateTime
| Value)
| >| | >| {
| >| | >| Initialise(new
| OptionalDateTime
| >| | >| (Value));
| >| | >| }
| >| | >| public void Initialise()
| >| | >| {
| >| | >| Initialise(new
| OptionalDateTime
| >| | >| ());
| >| | >| }
| >| | >| #endregion
| >| | >| }
| >| | >| }
| >| | >|
| >| | >| ##############OptionalDateTime Source##########
| >| | >|
| >| | >| [Serializable()]
| >| | >| public class OptionalDateTime
| >| | >| {
| >| | >| #region Enum
| >| | >| /// <summary>
| >| | >| /// Formats available - extend as
| >| | >| required, but remember to update <see
| >| | cref="GetValue"/>.
| >| | >| /// </summary>
| >| | >| public enum enumDateTimeFormat
| >| | >| {
| >| | >| /// <summary>
| >| | >| /// LongDateFormat
| >| | >| /// </summary>
| >| | >| LongDateFormat,
| >| | >| /// <summary>
| >| | >| /// LongTimeFormat
| >| | >| /// </summary>
| >| | >| LongTimeFormat,
| >| | >| /// <summary>
| >| | >| /// ShortDateFormat
| >| | >| /// </summary>
| >| | >| ShortDateFormat,
| >| | >| /// <summary>
| >| | >| /// ShortTimeFormat
| >| | >| /// </summary>
| >| | >| ShortTimeFormat
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Fields
| >| | >| private DateTime mDate;
| >| | >| private bool mIsNull;
| >| | >| #endregion
| >| | >|
| >| | >| #region Constructor
| >| | >| /// <summary>
| >| | >| /// Constructor - initialises a
| null
| >| | >| OptionalDateTime
| >| | >| /// </summary>
| >| | >| public OptionalDateTime()
| >| | >| {
| >| | >| mIsNull = true;
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Constructor - initialise an
| >| | >| OptionalDateTime to contain the value of a string.
| >| | >| /// If the string is not a valid
| >| | >| DateTime, the object is set to contain a null
| date.
| >| | >| /// </summary>
| >| | >| /// <param name="value">A string
| >| | >| representing a valid date.</param>
| >| | >| public OptionalDateTime(string
| value)
| >| | >| {
| >| | >| SetValue(value);
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Constructor - initialise an
| >| | >| OptionalDateTime to contain the value of a
| DateTime.
| >| | >| /// </summary>
| >| | >| /// <param name="value">A
| DateTime value
| >| | >| type.</param>
| >| | >| public OptionalDateTime(DateTime
| value)
| >| | >| {
| >| | >| SetValue(value);
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Public Methods
| >| | >| /// <summary>
| >| | >| /// Set the value of the object
| to equal
| >| | >| that of a DateTime.
| >| | >| /// </summary>
| >| | >| /// <param name="value">A
| >| | >| DateTime.</param>
| >| | >| public void SetValue(DateTime
| value)
| >| | >| {
| >| | >| mDate = value;
| >| | >| mIsNull = false;
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Set the value of the object
| to equal
| >| | >| that of a string. If the string is not a valid
| >| | >| /// DateTime, the object is set
| to
| >| | >| contain a null date.
| >| | >| /// </summary>
| >| | >| /// <param name="value">A string
| >| | >| representing a valid date.</param>
| >| | >| public void SetValue(string value)
| >| | >| {
| >| | >| if(value == null || value
| == "")
| >| | >| {
| >| | >| mIsNull = true;
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >| try
| >| | >| {
| >| | >| mDate =
| >| | >| DateTime.Parse(value);
| >| | >| mIsNull =
| false;
| >| | >| }
| >| | >| catch
| >| | >| {
| >| | >| throw new
| >| | >| ArgumentException("The string entered cannot be
| >| | converted
| >| | >| to a DateTime", "value");
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Return the value of the
| object as a
| >| | >| string with optional formatting.
| >| | >| /// </summary>
| >| | >| /// <param name="Format">The
| format to
| >| | >| return.</param>
| >| | >| /// <returns>A string containing
| the
| >| | >| correctly formatted date.</returns>
| >| | >| public string GetValue
| (enumDateTimeFormat
| >| | >| Format)
| >| | >| {
| >| | >| if(mIsNull)
| >| | >| {
| >| | >| return "";
| >| | >| }
| >| | >| else
| >| | >| {
| >| | >| switch(Format)
| >| | >| {
| >| | >| case
| >| | >| enumDateTimeFormat.LongDateFormat:
| >| | >|
| return
| >| | >| mDate.ToLongDateString();
| >| | >| case
| >| | >| enumDateTimeFormat.LongTimeFormat:
| >| | >|
| return
| >| | >| mDate.ToLongTimeString();
| >| | >| case
| >| | >| enumDateTimeFormat.ShortDateFormat:
| >| | >|
| return
| >| | >| mDate.ToShortDateString();
| >| | >| case
| >| | >| enumDateTimeFormat.ShortTimeFormat:
| >| | >|
| return
| >| | >| mDate.ToShortTimeString();
| >| | >| default:
| >| | >|
| throw new
| >| | >| UnhandledDateFormatException(Format);
| >| | >| }
| >| | >| }
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Return the value of the
| object as a
| >| | >| ShortDateString.
| >| | >| /// </summary>
| >| | >| /// <returns></returns>
| >| | >| public string GetValue()
| >| | >| {
| >| | >| return GetValue
| >| | >| (enumDateTimeFormat.ShortDateFormat);
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Public Override Methods
| >| | >| /// <summary>
| >| | >| /// Passes a string containing
| the date
| >| | >| in <see
| cref="enumDateTimeFormat.ShortDateFormat"/>.
| >| | >| /// </summary>
| >| | >| /// <returns>The date returned.
| Passes an
| >| | >| empty string for blank (null) dates.</returns>
| >| | >| public override string ToString()
| >| | >| {
| >| | >| return GetValue();
| >| | >| }
| >| | >| #endregion
| >| | >|
| >| | >| #region Properties
| >| | >| /// <summary>
| >| | >| /// Returns the date of the
| >| | >| OptionalDateTime as a DateTime type. Raises the
| >| | >| /// <see
| >| | >| cref="OptionalDateTimeIsNullException"/> if the
| >| | >| OptionalDateTime is
| >| | >| /// blank (null). Check the <see
| >| | >| cref="IsNull"/> property before calling this
| >| | >| /// method to avoid the exception.
| >| | >| /// </summary>
| >| | >| public DateTime GetDateTime
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| if(mIsNull)
| >| | >| {
| >| | >| throw new
| >| | >| OptionalDateTimeIsNullException();
| >| | >| }
| >| | >| return mDate;
| >| | >| }
| >| | >| }
| >| | >| /// <summary>
| >| | >| /// Gets a boolean value
| indicating
| >| | >| whether the OptionalDateTime is blank (null).
| >| | >| /// </summary>
| >| | >| public bool IsNull
| >| | >| {
| >| | >| get
| >| | >| {
| >| | >| return mIsNull;
| >| | >| }
| >| | >| }
| >| | >| #endregion
| >| | >| }
| >| | >|
| >| | >| thanks in advance
| >| | >|
| >| | >
| >| | >.
| >| | >
| >| |
| >|
| >
| >.
| >
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top