AlainD
AlainD

Reputation: 6597

Show invalid dates as disabled in TDateTimePicker

I am using a TDateTimePicker to allow the user to select a day (either manually or by clicking buttons to go forward or back one day). The user will then see log entries for that particular day.

The control works great, but I want to restrict the user to between [OLDEST-DAY-IN-LOG] and [TODAY], because those are the date limits where there is data.

I've set the MinDate and MaxDate on the TDateTimePicker and that works fine. Selecting a date outside the allowed range does nothing.

My question is whether it is possible to draw the invalid dates greyed out. In the attached image, the date selected is 01/04 and today is 02/04. I'd like to see 03/04 (and later) disabled. Ideally, like the "30" and "31" you see in the image which are the last days of March.

Is this possible? Using Delphi 7 if that is relevant.

TDateTimePicker control in Delphi

Upvotes: 4

Views: 1702

Answers (2)

moskito-x
moskito-x

Reputation: 11958

As already, mentioned in comments and the answer only styles normal and bold can used. With TYearBoldManager you can implement that.

only set March 30,31 and April 1,2,3,4

Tested : Delphi5 on win XP/3

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

you can set the bold dates with

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;

Then you should change the color values to get the best possible contrast. Here are just a suggestion.

enter image description here

enter image description here

to Test there are 4 files here , MonthCalendarDemo

Update :

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.

Look at UMonthBoldStorage.pas how it's done.


What is the difference here ?

enter image description here

The experts have recognized it.

to the right TDateTimePicker

on the left a TMonthCalendar and a TComboBox

Advantage:

  • No min- maxDate needed
  • can have days without logfile.
  • full control over the calendar.
  • bold days are easy to use
  • can see where you clicked (Look at the nice dotted border at 25. But has no effect on the calendar).
  • no disappear if you click on the wrong date.(can click as much as you want , calendar will only disappear when you double-click on bold days. here : days 20 and 22).

enter image description here

  • can click inside the TComboBox or on the down-arrow or when focused hit ENTER opens the calendar and brings you to the last date with a logfile.

enter image description here

enter image description here

  • from there you can comfortably, with the arrow keys, the months with days that have a logfile go through.

enter image description here

all described could be accomplished with a few lines additional code

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;

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595971

TDateTimePicker is a wrapper for a Win32 DTP control, which does not provide the functionality you are looking for. There is no option for custom drawing the drop-down calendar, and the only per-day styles available are normal and bold.

Upvotes: 2

Related Questions