【问题标题】:Show invalid dates as disabled in TDateTimePicker在 TDateTimePicker 中将无效日期显示为禁用
【发布时间】:2015-04-02 14:18:06
【问题描述】:

我正在使用 TDateTimePicker 允许用户选择一天(手动或通过单击按钮前进或后退一天)。然后,用户将看到该特定日期的日志条目。

控件效果很好,但我想将用户限制在 [OLDEST-DAY-IN-LOG] 和 [TODAY] 之间,因为这些是有数据的日期限制。

我已经在 TDateTimePicker 上设置了 MinDate 和 MaxDate 并且效果很好。选择允许范围之外的日期没有任何作用。

我的问题是是否可以将无效日期绘制为灰色。在附图中,选择的日期是 01/04,今天是 02/04。我希望看到 03/04(及以后)被禁用。理想情况下,就像您在图像中看到的“30”和“31”,它们是三月的最后几天。

这可能吗?如果相关,请使用 Delphi 7。

【问题讨论】:

  • MinDate 和 MaxDate 已设置(有问题)并且有效。当用户选择 03/04 时,控件不会生成“OnChange”或“CloseUp”事件。通过将无效日期变灰,用户至少会明白为什么什么都没发生。
  • 使用 TMonthCalendar,如果使用 xpmanifest,则 min-max 之间的范围是唯一可见的天数。
  • @SertacAkyuz:使用 TMonthCalendar 的有趣想法,以前从未使用过其中之一。我的日期选择器很小,像下拉列表一样位于表单的顶部。 TMonthCalendar 似乎有一个(相当大的)最小尺寸,使其不适合我的用户界面。看不到任何属性来更改其样式,可以这样做吗?
  • 其实我只是用 TDateTime 选择器测试过,两个控件的日历是一样的。您只需要使用“xpman”,就可以继续使用选择器。

标签: delphi tdatetimepicker


【解决方案1】:

TDateTimePicker 是 Win32 DTP control 的包装器,它不提供您正在寻找的功能。没有自定义绘制下拉日历的选项,唯一可用的每日样式是 normalbold

【讨论】:

  • 谢谢雷米。在列出的设置 bold 格式并查看它的外观的属性和方法中,没有什么能让我立即跳出来。如果我可以将最小/最大日期设置为粗体,那可能会起作用......
  • @AlainD:查看BoldDays 属性。
  • @KenWhite:BoldDays 是一种方法,而不是一种属性。它准备了一组日状态,但实际上并不将该数组分配给 DTP。您必须为此使用OnGetMonthInfoOnGetMonthBoldInfo 事件,或拦截MCN_GETDAYSTATE 通知。见stackoverflow.com/questions/7210565
  • @Remy:是的,我说错了。内存故障;当您的评论进入我的收件箱时,我正在查找它。
  • @AlainD:你不能总是相信 MSDN 关于大多数 API 的最低操作系统版本的说法。当微软放弃对操作系统的支持时(就像他们最近对 XP 所做的那样),它通常会在整个 MSDN 中放弃提及该操作系统。有大量 API 文档不再提及 2000 和 XP 作为最低操作系统版本,即使这些 API 确实存在于 2000 和 XP 中。特别是,从 ComCtl32.dll v4.70 开始支持MCN_GETDAYSTATE 通知,该通知包含在 Windows 95 OSR2 中的 Internet Explorer 3 中。
【解决方案2】:

正如已经在 cmets 中提到的,答案只有样式 normal and bold 可以使用。使用TYearBoldManager,您可以实现它。

仅设置为 3 月 30,31 日和 4 月 1,2,3,4 日

测试:Delphi5 on win XP/3

minDate = 2015/03/30maxDate = 2015/04/04

您可以设置bold 日期

procedure TForm1.FormCreate(Sender: TObject);
begin
   MonthCalendar1.CalColors.MonthBackColor :=  $6A7678;
   MonthCalendar1.CalColors.TextColor := $4D5858;

   FYearBoldManager := TYearBoldManager.Create;
   FYearBoldManager.MakeBold(3, 30);
   FYearBoldManager.MakeBold(3, 31);
   FYearBoldManager.MakeBold(4, 1);
   FYearBoldManager.MakeBold(4, 2);
   FYearBoldManager.MakeBold(4, 3);
   FYearBoldManager.MakeBold(4, 4);
   ...
end;

然后您应该更改颜色值以获得最佳对比度。这里只是一个建议。

测试有4个文件here , MonthCalendarDemo

更新:

MonthCalendarDemo.dpr

program MonthCalendarDemo;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  UMonthBoldStorage in 'UMonthBoldStorage.pas';

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

看看UMonthBoldStorage.pas是怎么做的。


这里有什么区别?

专家们已经认识到了。

向右TDateTimePicker

左边是TMonthCalendarTComboBox

优势:

  • 不需要 min-maxDate
  • 可以有days without logfile
  • 完全控制日历。
  • 粗体字好用
  • 可以看到您点击的位置(查看25 的漂亮虚线边框。但对日历没有影响)。
  • 点击错误的日期不会消失。(可以随意点击,只有双击粗体时日历才会消失。这里:第 20 天和第 22 天)。

  • 可以在TComboBox 内部或down-arrow 上单击,或者当重点点击时ENTER 打开日历并通过日志文件将您带到最后一个日期。

  • 您可以从那里轻松地使用箭头键查看有日志文件的月份和日期。

所有描述都可以通过几行附加代码来完成

procedure TForm1.MonthCalendar1DblClick(Sender: TObject);
var
   year, month, day : Word;
begin
    DecodeDate(MonthCalendar1.Date,Year, Month, Day);
    if FYearBoldManager.GetDayStatus(month, day) then begin
       if ValidDate then MonthCalendar1.Visible:=False;
    end;
end;

procedure TForm1.MonthCalendar1Click(Sender: TObject);
var
   year, month, day : Word;
begin
   DecodeDate(MonthCalendar1.Date,Year, Month, Day);
   if FYearBoldManager.GetDayStatus(month, day) then begin
      lastValidDate := MonthCalendar1.Date;
      ValidDate:=True;
   end else begin
      MonthCalendar1.Date := lastValidDate;
      ValidDate:=False;
   end;
end;

function TForm1.getComboBoxText(var validText:AnsiString):Boolean;
var
actText :AnsiString;

begin
    if ComboBox1.Text = '' then  actText := validText else actText := ComboBox1.Text;
    Try
    MonthCalendar1.Date :=  StrToDateTime(Copy(actText,1,10));
    if actText <> validText then validText := actText;
    lastValidDate := MonthCalendar1.Date;
    ValidDate:=True;
    Result := True;
    except
      Result := False;
    end;
end;

procedure TForm1.ComboBox1Click(Sender: TObject);
begin
     if getComboBoxText(validText) then MonthCalendar1.Visible:=True;
end;

procedure TForm1.ComboBox1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     if getComboBoxText(validText) then MonthCalendar1.Visible:=True;
end;

【讨论】:

  • 请注意,此代码适用于TMonthCalendar,而不是@AlainD 正在使用的TDateTimePicker
猜你喜欢
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多