【发布时间】:2009-03-18 12:07:13
【问题描述】:
我有一个 DateTimePicker(可空版本),我需要只读。如果它被禁用,我对显示不满意,所以想知道是否有人有一个很好的例子来说明如何停止现场更新?
谢谢。
【问题讨论】:
我有一个 DateTimePicker(可空版本),我需要只读。如果它被禁用,我对显示不满意,所以想知道是否有人有一个很好的例子来说明如何停止现场更新?
谢谢。
【问题讨论】:
我知道这已经很老了,但为了帮助其他人搜索这个(因为这是我通过谷歌找到的第一个)你可以使用:
this.dateTimePicker1.Enabled = false;
使其行为方式与 this.textbox1.ReadOnly = true 的文本框相同
【讨论】:
ReadOnly = true 所没有的灰色外观。
您可以挂钩 Changed 事件,并将值设置回您想要的值(如果不同)——这样您就可以覆盖任何更改的原因(通过鼠标或键盘)
您是否考虑过使用不同的控件,例如只读文本框甚至标签控件?
【讨论】:
这个问题 - 六年后 - 似乎仍然引起了一些兴趣,所以我会投入 2 美分:对我有用的是 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();
}
}
}
【讨论】:
作为另一个建议:使用文本框(或标签)并使其只读。在里面显示你想要的值。
如果您必须有一个日期时间选择器,请同时创建一个日期时间选择器和一个文本框。将它们叠放在一起。当您需要 datetimepicker 时,隐藏文本框。等等。
【讨论】:
在 Keydown 上:e.SuppressKeyPress = true;为我工作,仍然可以选择日期,但无法手动输入
【讨论】:
“如果显示器被禁用,我不满意”
为什么?如果是因为禁用的文本框看起来很奇怪,您可以更改禁用的样式以使其看起来正常,或者以更漂亮的方式指示它只接受通过日期选择器的输入。可能没有边框,说它不是真正的文本框。
【讨论】:
我这样做的一种方法是简单地将允许的日期范围限制为单个值。
dateTimePicker.MinDate = dateTimePicker.Value;
dateTimePicker.MaxDate = dateTimePicker.Value;
【讨论】:
我知道它已经过时了,但我讨厌找到仍然相关但没有解决方案的问题。顺便说一句,您可能不想禁用它的原因是您无法轻松显示工具提示和自定义背景色(尽管这可以更轻松地解决)
无论如何,我找到了我相信问题提出的解决方案(感谢其他地方的其他人)。我已经有了 DateTimePicker 的自定义控件。
然后我添加了一个只读属性。我的问题出在 VB.Net 项目中
如果 Readonly = True,则覆盖 KeyDown 事件并标记为已处理。
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If mReadOnly Then
e.Handled = True
Else
MyBase.OnKeyDown(e)
End If
End Sub
这会处理箭头键和 F4 下拉键。
然后要禁用下拉菜单,重写 WndProc 方法:
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
为了使它在我的 OnPaint 覆盖中看起来是只读的,我有以下内容:
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
【讨论】:
处理 DateTimePicker.MouseClick 事件并将 event.handled 设置为 true
【讨论】:
选择 Changed 事件并设置 e.Cancel = true 怎么样?
【讨论】:
这不是最好的方法,但这确实会停止通过 keyUp 更新日期时间
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); 开始 dtpDate.DateTime := oldDtpDate; 结束;
procedure TForm1.dtpDateExit(Sender: TObject);
begin
dtpDate.DateTime := oldDtpDate;
end;
【讨论】:
this.dateTimePicker1.Enabled = false;
这是一种简单而完美的解决方案。
【讨论】:
dateTimePicker2.Enabled = false;
【讨论】:
试试这个:
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dateTimePicker1.Value = DateTime.Now;
}
【讨论】:
DateTime.Now 不是您希望能够使用的唯一值。