我有一个DateTimePicker(可为空版本),需要它是只读的。如果将其禁用,我对其显示不满意,想知道是否有人有如何停止字段更新的巧妙示例?
谢谢。
我知道这篇文章很老,但是如果有其他人在搜索时需要帮助(因为我第一次通过谷歌找到它),你可以使用以下方法:
this.dateTimePicker1.Enabled = false;
使其表现与文本框相同,就像使用this.textbox1.ReadOnly = true
时一样。
你可以挂接Changed事件,如果值有改变就将其设置回所需的值(如果不同的话)-这样你就可以覆盖任何通过鼠标或键盘引起的更改。
你是否考虑过使用不同的控件,例如只读文本框或甚至标签控件?
这个问题——六年后——似乎仍然引起了一些关注,所以我会分享我的两分钱:对我来说有效的方法是1)创建一个UserControl并将基类更改为DateTimePicker 2)每当值发生变化时,拍摄控件的一个小位图快照 3)拦截WM_PAINT消息,并且如果我们的控件被禁用,则绘制位图而不是控件。 (注意:designer.cs中的AutoScaleMode属性会导致编译错误,所以只需删除即可)。
public partial class DateTimePickerWithReadOnly : DateTimePicker
{
Bitmap ReadOnlyImage;
// We maintain a "shadow" control to avoid capturing selections in the snapshot.
// If you use different formatting or styles just make sure the shadow is set to match!
DateTimePicker Shadow = new DateTimePicker();
public DateTimePickerWithReadOnly()
{
InitializeComponent();
CaptureBitmap();
this.ValueChanged += new EventHandler(DateTimePickerWithReadOnly_ValueChanged);
}
private void CaptureBitmap()
{
Shadow.Value = Value;
Shadow.Size = Size;
ReadOnlyImage = new Bitmap(Width, Height);
Shadow.DrawToBitmap(ReadOnlyImage, new Rectangle(0, 0, Size.Width, Size.Height));
}
void DateTimePickerWithReadOnly_ValueChanged(object sender, EventArgs e)
{
CaptureBitmap();
}
protected override void DefWndProc(ref Message m)
{
base.DefWndProc(ref m);
// WM_PAINT is 0x000F
if ((m.Msg == 0x000F) && !Enabled)
{
Graphics g = base.CreateGraphics();
g.DrawImage(ReadOnlyImage, new Rectangle(0, 0, Size.Width, Size.Height));
g.Dispose();
}
}
}
在按下键盘时:e.SuppressKeyPress = true; 对我有用,我仍然可以选择日期,但无法手动输入
我曾经采用的一种方法是将可允许的日期范围限制为单个值。
dateTimePicker.MinDate = dateTimePicker.Value;
dateTimePicker.MaxDate = dateTimePicker.Value;
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If mReadOnly Then
e.Handled = True
Else
MyBase.OnKeyDown(e)
End If
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
' m.Msg = 0x201 / &H201 = WM_LBUTTONDOWN
' m.Msg = 0x203 / &H203 = WM_LBUTTONDBLCLK
If ReadOnly And (m.Msg = &H201 Or m.Msg = &H203) Then
Return
End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim g As Graphics = Me.CreateGraphics()
Dim dropDownIcon As Rectangle = New Rectangle(ClientRectangle.Width - 17, 0, 17, ClientRectangle.Height)
Dim b As Brush
Dim v As VisualStyles.ComboBoxState
Dim vn As ButtonState
b = New SolidBrush(Me.BackColor)
If Me.IsReadOnly Then
v = VisualStyles.ComboBoxState.Disabled
vn = ButtonState.Inactive
Else
b = New SolidBrush(Me.BackColor)
v = VisualStyles.ComboBoxState.Normal
vn = ButtonState.Normal
End If
'changed to only do this if the control is visible
If Me.Visible = True Then
'colour rectangle
g.FillRectangle(b, 0, 0, ClientRectangle.Width, ClientRectangle.Height)
'for border
g.DrawRectangle(System.Drawing.SystemPens.ActiveBorder, 0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1)
'for text
g.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), 0, 2)
'we need to render the dropdown when visual styles is not turned on
If ComboBoxRenderer.IsSupported Then
ComboBoxRenderer.DrawDropDownButton(g, dropDownIcon, v)
Else
ControlPaint.DrawComboButton(g, dropDownIcon, vn)
End If
End If
g.Dispose()
b.Dispose()
End Sub
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private DateTime originalValue;
private void dateTimePicker1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
originalValue = dateTimePicker1.Value;
}
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dateTimePicker1.Value = originalValue;
}
}
首先,我们必须记住原始日期时间。
procedure TForm1.dtpDateEnter(Sender: TObject);
begin
oldDtpDate := dtpDate.DateTime;
end;
在TForm1.dtpDateClick(Sender: TObject)过程中: begin dtpDate.DateTime := oldDtpDate; end;
procedure TForm1.dtpDateExit(Sender: TObject);
begin
dtpDate.DateTime := oldDtpDate;
end;
ReadOnly = true
中是不存在的。 - Broots Waymb