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

Delphi 在TDateTimePicker中将无效日期显示为禁用,delphi,tdatetimepicker,Delphi,Tdatetimepicker,我使用TDateTimePicker允许用户选择一天(手动或通过单击按钮前进或后退一天)。然后,用户将看到该特定日期的日志条目 该控件工作得很好,但我想将用户限制在[Olester-DAY-IN-LOG]和[TODAY]之间,因为这些是存在数据的日期限制 我已经在TDateTimePicker上设置了MinDate和MaxDate,效果很好。选择超出允许范围的日期不起任何作用 我的问题是是否有可能把无效日期画成灰色。在附图中,所选日期为01/04,今天为02/04。我希望看到03/04(及更高版

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

该控件工作得很好,但我想将用户限制在[Olester-DAY-IN-LOG]和[TODAY]之间,因为这些是存在数据的日期限制

我已经在TDateTimePicker上设置了MinDate和MaxDate,效果很好。选择超出允许范围的日期不起任何作用

我的问题是是否有可能把无效日期画成灰色。在附图中,所选日期为01/04,今天为02/04。我希望看到03/04(及更高版本)被禁用。理想情况下,就像你在图片中看到的“30”和“31”,这是三月的最后几天

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


TDateTimePicker
是Win32的包装器,它不提供您想要的功能。没有用于自定义绘制下拉日历的选项,每天可用的样式只有普通和粗体。

如注释和答案中所述,只能使用样式
普通和粗体。使用
TYearBoldManager
可以实现这一点

仅设定3月30日、31日和4月1日、2日、3日、4日

测试:Delphi5在win XP/3上运行

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

您可以使用设置日期

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个文件

更新:

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

左侧有一个
t月历
和一个
t邮箱

优点:

  • 不需要最小-最大日期
  • 可以有
    天没有日志文件
  • 完全控制日历
  • 大胆的日子很容易使用
  • 可以看到您单击的位置(查看
    25
    处漂亮的虚线边框,但对日历没有影响)
  • 如果您点击的日期不正确,日历不会消失。(您可以随意点击,只有双击粗体日期,日历才会消失。这里是:第20天和第22天)

  • 您可以单击
    t日历框内的
    向下箭头上的
    ,或者在重点点击
    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;
程序TForm1.MonthCalendar1DblClick(发送方:TObject);
变量
年、月、日:字;
开始
解码日期(MonthCalendar1.日期、年、月、日);
如果FYearBoldManager.GetDayStatus(月、日),则开始
如果有效,则MonthCalendar1.Visible:=假;
结束;
结束;
程序t用于m1.monthCalendar1点击(发送方:ToObject);
变量
年、月、日:字;
开始
解码日期(MonthCalendar1.日期、年、月、日);
如果FYearBoldManager.GetDayStatus(月、日),则开始
lastValidDate:=MonthCalendar1.日期;
ValidDate:=真;
结束,否则开始
MonthCalendar1.日期:=lastValidDate;
有效期:=假;
结束;
结束;
函数TForm1.getComboxText(var validText:AnsiString):布尔值;
变量
actText:AnsiString;
开始
如果ComboBox1.Text='',则actText:=validText,否则actText:=ComboBox1.Text;
尝试
MonthCalendar1.Date:=StrToDateTime(副本(actText,1,10));
如果actText validText,则validText:=actText;
lastValidDate:=MonthCalendar1.日期;
ValidDate:=真;
结果:=真;
除了
结果:=假;
结束;
结束;
程序TForm1.Combox1Click(发送方:ToObject);
开始
如果是getComboBoxText(validText),则MonthCalendar1.Visible:=True;
结束;
过程TForm1.ComboBox1KeyUp(发送方:ToObject;变量关键字:Word;
换档:t换档状态);
开始
如果是getComboBoxText(validText),则MonthCalendar1.Visible:=True;
结束;

MinDate和MaxDate已设置(如有疑问)且有效。当用户选择03/04时,控件不会生成“OnChange”或“CloseUp”事件。通过灰显无效日期,用户至少可以看到为什么什么都没有发生。使用TMonthCalendar,如果使用xpmanifest,最小-最大值之间的范围是唯一可见的日期。@SertacAkyuz:使用TMonthCalendar很有意思,以前从未使用过。我的日期选择器很小,位于表单顶部,就像一个下拉列表。TMMonthCalendar的最小大小(相当大),不适合我的用户界面。无法看到任何属性来更改其样式,可以这样做吗?实际上我刚刚使用TDateTime选择器进行了测试,两个控件的日历都是相同的。你只需要使用“xpman”,就可以继续使用选择器。谢谢雷米。在列出的属性和方法中,没有任何东西会立即跳出来设置粗体格式并查看其外观。如果我可以将最小/最大日期设置为粗体…@AlainD:请参阅
BoldDays
属性。@KenWhite:是一个方法,而不是属性。它准备一个日状态数组,但实际上并不将该数组分配给DTP。您必须为此使用或事件,或拦截
MCN\u GETDAYSTATE
通知。看@Remy:是的,我说错了。记忆故障;当你的评论出现在我的收件箱时,我正在查找它。@AlainD:你不能总是相信MSDN关于大多数API的最低操作系统版本的说法。当微软放弃对操作系统的支持时(就像他们最近对XP所做的那样),它通常会在整个过程中放弃对该操作系统的提及