我真的很困惑。我想做的事情(看起来非常简单)是在TDateTimePicker中显示日期+时间,并集成日历,并且能够在其值发生变化后读取它。
我想使用dd / MM / yyyy hh:mm格式。
由于TDateTimePicker不是TDateOrTimePicker,因此使用的是:
看起来不错,现在让我们读一下:
showmessage(DateTimeToStr(DateTimePicker1.Date));
仅正确显示日期。不考虑hh:mm部分的变化。我总是得到默认值。 然后我想:还有一个Time属性,也许我需要读取2次的值。
showmessage(DateTimeToStr(DateTimePicker1.Time));
showmessage(DateTimeToStr(DateTimePicker1.Date));
但我有与以前完全相同的输出(和问题)。现在,让我们尝试将此Kind属性更改为dtkTime,然后读取时间,然后将其切换回dtkDate,然后读取日期。
但不,它仍然无法奏效。将Kind属性从dtkDate切换到dtkTime会删除我在hh:mm部分的输入。
我知道我实际上应该使用2个TDateTimePickers:一个用于日期,一个用于时间。
所以我的问题是:
Delphi设计问题:
请注意,我发布这个问题主要是为了避免初学者做同样的调试和挫折的过程。
答案 0 :(得分:6)
我想做的事情(看起来非常简单)是在TDateTimePicker中显示日期+时间,并集成日历,并且能够在其值发生变化后读取它。
我想使用dd / MM / yyyy hh:mm格式
抱歉,但你不能。 TDateTimePicker
仅适用于日期或时间,但不能同时使用。
如果将Kind
属性设置为dtkDate
,则可以指定自定义DATE格式,但忽略任何TIME格式,并且使用Time
属性未定义。
如果将Kind
属性设置为dtkTime
,则可以指定自定义TIME格式,但忽略任何DATE格式,并且使用Date
属性未定义。
读取Date
属性时,只有值的DATE部分有效。在一个完美的世界中,TIME部分将始终为零,但我看到它有时会包含垃圾。但是,您可以使用DateUtils.DateOf()
函数轻松忽略它:
Value := DateOf(DateTimePicker1.Date);
与Time
属性和值的DATE部分相同。您可以使用DateUtils.TimeOf()
函数忽略任何潜在的垃圾:
Value := TimeOf(DateTimePicker1.Time);
有没有一种简单的方法可以解决我的简单和非常常见的问题(一个真正的DateTimePicker)?
使用TDateTimePicker
的唯一真正解决方案是使用两个单独的TDateTimePicker
控件,一个用于日期,另一个用于日期。您可以在需要时将两个值组合在一起:
Value := DateOf(DateTimePicker1.Date) + TimeOf(DateTimePicker2.Time)
如果您想显示TDateTime
,请执行相反的操作:
DateTimePicker1.Date := DateOf(Value);
DateTimePicker2.Time := TimeOf(Value);
否则,找到支持您需要的第三方选择器(或编写自己的选择器)。
为什么Format属性基本上没用且误导?
这不是无用和误导。它非常有用,但仅限于当前Kind
设置的范围内。
拥有TimeFormat,DateFormat和正确的格式验证过程并不难。
TDateTimePicker
只是Win32 Date and Time Picker control的一个瘦包装器,它没有这样的功能。当然,他们可以编写自定义逻辑,以允许在保留不同设置的Kind
值之间切换,但实际上并不是如何使用DTP控件。您设置Kind
一次,Format
一次,然后根据需要处理输入和输出。不来回切换。仅仅因为你可以动态切换Kind
并不意味着应该。如果您认为编写这样的自定义逻辑很容易,欢迎您使用自己的代码。
答案 1 :(得分:1)
这些天我遇到了同样令人沮丧的问题。但在我的情况下,我只需要从TDateTimePicker字段中获取完整的日期和时间(不需要以编程方式设置它,但这不是很困难)。所以我做的是创建我自己的TDateTimePicker并创建一个新的公共属性,获取字段Caption并设置为DateTime(Caption受documentation保护。这是我的代码:
unit uZDateTimePicker;
interface
uses
Vcl.ComCtrls, SysUtils;
type
TZDateTimePicker = class(TDateTimePicker)
private
procedure SetDateAndTime;
protected
procedure Change; override;
end;
implementation
{ TZDateTimePicker }
procedure TZDateTimePicker.Change;
begin
SetDateAndTime
end;
procedure TZDateTimePicker.SetDateAndTime;
begin
DateTime := StrToDateTime(Caption);
inherited;
end;
end.
就这么简单。
此外,如果您使用DevExpress组件,您将使用可以正常工作的TcxDateEdit。
答案 2 :(得分:1)
我有完全相同的问题。 安德烈解决方案的作用就像安德烈的魅力一样。
问题:我们需要创建一个新单元,创建一个新组件并将组件注册到另一个包,以便能够在设计时设置表单。
解决方案:为了避免这种情况,只需在您使用TDateTimePicker组件的表单中声明以下类:THackDateTimePicker
...
type
// this class is just to access protected Caption property
THackDateTimePicker = class(TDateTimePicker);
TSymbolInfoForm = class(TForm)
...
end;
然后只需实现OnChange事件:
procedure TSymbolInfoForm.dtpChange(Sender: TObject);
begin
TDatetimePicker(Sender).Datetime := StrToDateTime(THackDateTimePicker(Sender).Caption);
end;
您可以将同一表单上所有TDateTimePicker组件的所有OnChange事件链接到理智的OnChange事件......瞧!
答案 3 :(得分:-1)
以上答案都是正确的,您可以从datetimepicker.DateTime属性中获取datetime,也可以通过将“ Format”属性设置为dd / MM / yyyy hh:mm来显示日期和时间