在 TDateTimePicker 中将无效日期显示为禁用

Show invalid dates as disabled in TDateTimePicker

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

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

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

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

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

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

如前所述,评论和答案中提到的只能使用样式 normal and bold。使用 TYearBoldManager 你可以实现它。

只设置30、31和4月1、2、3、4

已测试:Delphi5 在 win XP/3

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

您可以将 bold 日期设置为

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

   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

左边一个TMonthCalendar和一个TComboBox

优点:

  • 不需要最小-最大日期
  • 可以有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;