TDateTimePicker中的另一个错误?

时间:2018-08-15 11:56:01

标签: delphi datetimepicker delphi-2009

我发现,在将TDateTimePicker的MaxDate设置为非零值之后,不可能将其恢复为零(禁用它)。我的意思是,MaxDate读取零,但最大范围仍对之前设置的值有效。可以通过下拉日历并检查最后一个可见日期来注意到这一点。

这是另一个错误,还是我不了解如何禁用MaxDate?

procedure TForm1.Button1Click(Sender: TObject);
begin
 DateTimePicker1.MaxDate:= Date + 10;
 DateTimePicker1.MaxDate:= 0;
 Caption:= IntToStr(Trunc(Test.MaxDate));
end;

P.S:我会先将“时间”设置为零(这是另一个错误)。

2 个答案:

答案 0 :(得分:2)

以下内容不是MSDN记录的(偶然发现的),但它似乎有效(至少在Windows 7上)。您可以尝试调用以下宏(或发送相应的消息)以消除日期时间选择器控件的时间范围限制:

DateTime_SetRange(DateTimePicker1.Handle, 0, nil);

我的幸运偶然试验是通过在没有时间范围的情况下发送DTM_SETRANGE消息时不使用 GDTR_MIN GDTR_MAX 标志开始的,因此(我已经通过了< strong> 0 和 nil )。

如果您将此作为可能的解决方法,则VCL剩下的是重置内部字段值,例如做一个小帮手可能会变成:

uses
  CommCtrl;

type
  TDateTimePickerHelper = class helper for TDateTimePicker
  public
    procedure ResetRange;
  end;

implementation

{ TDateTimePickerHelper }

procedure TDateTimePickerHelper.ResetRange;
var
  DateRange: array[0..1] of TDate;
begin
  DateRange[0] := MinDate; { ← store the current MinDate }
  DateRange[1] := MaxDate; { ← store the current MaxDate }

  MinDate := 0; { ← set the control's MinDate internal field to 0 }
  MaxDate := 0; { ← set the control's MaxDate internal field to 0 }

  if not DateTime_SetRange(Handle, 0, nil) then { ← if the macro fails, then... }
  begin
    MinDate := DateRange[0]; { ← restore the previous MinDate internal field value }
    MaxDate := DateRange[1]; { ← restore the previous MaxDate internal field value }
  end;
end;

然后使用它重置范围:

procedure TForm1.Button1Click(Sender: TObject);
begin
  DateTimePicker1.ResetRange;
end;

答案 1 :(得分:2)

Victoria discovered意外地是Win32 Date and Time Picker control可以通过使用未记录的技巧来重置其范围。

但是,Victoria的答案在Delphi 10.2中不起作用,因为VCL包装器的内部max和min字段未正确重置为0。不会将MinDateMaxDate属性更改为0 -不会将FMinDateFMaxDate字段设置为{{1} }归功于属性设置器的实现。

这将使控制失效。

一种解决方法是直接设置字段(我还对Victoria的逻辑进行了一些调整,以使代码更简洁):

0

type TCommonCalendarHelper = class helper for TCommonCalendar procedure ResetRangeFields; end; TDateTimePickerHelper = class helper for TDateTimePicker public procedure ResetRange; end; { TDateTimePickerHelper } procedure TDateTimePickerHelper.ResetRange; begin if DateTime_SetRange(Handle, 0, nil) then ResetRangeFields; end; { TCommonCalendarHelper } procedure TCommonCalendarHelper.ResetRangeFields; begin with Self do begin FMinDate := 0; FMaxDate := 0; end; end; 结构在这里很有必要,请参阅https://stackoverflow.com/a/42936824/282848。)

要尝试此操作:

with

当然,此代码依赖于未记录的Win32功能和VCL实现细节。但是,危险可能很小。有关此主题的更详尽讨论,请参见Victoria的评论。如果您知道VCL版本,则使用此代码(仅)可能是合理的。 (您甚至可以使它不能在将来的VCL版本上编译。)