I know there's a way to highlight a cell in a TStringGrid
. I could use that, but inputting the dates and days and months would be a big issue unless you know how to do that.

- 555,201
- 31
- 458
- 770

- 21
- 1
1 Answers
Yes, this is easy if you only make a small modification to the control's source code. Specifically, we need to add a small amount of code to its DrawCell
method.
Initially, this is
procedure TCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
TheText: string;
begin
TheText := CellText[ACol, ARow];
with ARect, Canvas do
TextRect(ARect, Left + (Right - Left - TextWidth(TheText)) div 2,
Top + (Bottom - Top - TextHeight(TheText)) div 2, TheText);
end;
Change this to:
procedure TCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
TheText: string;
i: Integer;
Day: Integer;
begin
TheText := CellText[ACol, ARow];
with ARect, Canvas do
begin
Font.Style := [];
for i := Low(HighlightDates) to High(HighlightDates) do
if TryStrToInt(TheText, Day) then
if SameDate(HighlightDates[i], EncodeDate(Year, Month, Day)) then
begin
Font.Style := [fsBold];
Break;
end;
TextRect(ARect, Left + (Right - Left - TextWidth(TheText)) div 2,
Top + (Bottom - Top - TextHeight(TheText)) div 2, TheText);
end;
end;
The easiest way to quickly try this is to use an interposer class:
type
TCalendar = class(Vcl.Samples.Calendar.TCalendar)
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
end;
TForm1 = class(TForm)
...
Now you only need to supply an array of dates to highlight:
var
HighlightDates: TArray<TDate>;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetLength(HighlightDates, 3);
HighlightDates[0] := EncodeDate(2020, 07, 10);
HighlightDates[1] := EncodeDate(2020, 07, 20);
HighlightDates[2] := EncodeDate(2020, 08, 10);
end;
or, in new Delphi versions (XE7 and later),
procedure TForm1.FormCreate(Sender: TObject);
begin
HighlightDates :=
[
EncodeDate(2020, 07, 10),
EncodeDate(2020, 07, 20),
EncodeDate(2020, 08, 10)
];
end;
Don't forget to add DateUtils
to the uses
clause.
(I apologise for the Swedish day names.)
Needless to say, you can paint highlighted cells in any way you like; making the font bold is only one possibility. If instead you want to highlight a cell by drawing a benzene ring in its top-right corner, that's fine too.
You will want to create a new control with the new code. In this, the date array would be a member. It could have an associated property with a setter that also invalidates the control. In addition, you could add public HighlightDate(const ADate: TDate)
and StopHighlightDate(const ADate: TDate)
procedures that add and remove dates from this array (and invalidate the control).
Update
On request (see comments), here is how to change the background colour of highlighted cells:
{ TCalendar }
procedure TCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState);
var
TheText: string;
i: Integer;
Day: Integer;
OldColor: TColor;
begin
TheText := CellText[ACol, ARow];
with ARect, Canvas do
begin
OldColor := Brush.Color;
for i := Low(HighlightDates) to High(HighlightDates) do
if TryStrToInt(TheText, Day) then
if SameDate(HighlightDates[i], EncodeDate(Year, Month, Day)) then
begin
Brush.Color := clSkyBlue;
FillRect(ARect);
Break;
end;
TextRect(ARect, Left + (Right - Left - TextWidth(TheText)) div 2,
Top + (Bottom - Top - TextHeight(TheText)) div 2, TheText);
Brush.Color := OldColor;
end;
end;

- 105,602
- 8
- 282
- 384
-
You can always open the file manually. On my system, it is located in `C:\Program Files (x86)\Embarcadero\Studio\20.0\source\vcl`. On your system, the version number is certainly different. – Andreas Rejbrand Jul 28 '20 at 18:27
-
hey i have an issue normally how I would access the calendar class by right-clicking and then clicking find declaration but when I do that it says unable to locate calendar.pas i actally want to highlight the text and change the cell color to red from a database i actually found a question like that but it was on mobile and a different version of Delphi [link](https://stackoverflow.com/questions/33632022/how-to-change-cell-color-in-a-tcalendar-component-in-delphi) im sorry i hav no idea on how to use an interposer class: i actually added it under type and the 'Vcl.Samples.'GotHighlighted – Heartfire 12 Jul 28 '20 at 18:30
-
How would i further color the cell red – Heartfire 12 Jul 28 '20 at 18:32
-
Set `Canvas.Brush.Color := clRed` and use `TCanvas.FillRect` to fill the cell. Do this before you draw the text (otherwise you will hide your text with the red rectangle). – Andreas Rejbrand Jul 28 '20 at 18:35
-
thanks you really helped me out any idea on how to change the cell color – Heartfire 12 Jul 28 '20 at 18:40
-
hey when i copy and paste the code then try to save it delphi gives me and error and says unable to create back up folder – Heartfire 12 Jul 28 '20 at 18:53
-
Are you trying to save files to `C:\Program Files (x86)\...`? That's not possible. Windows won't let you access these protected folders. You should save your code in your personal folders, e.g. `C:\Users\Andreas Rejbrand\Documents` in my case. – Andreas Rejbrand Jul 28 '20 at 18:58
-
@AndreasRejbrand This is exactly what I need, but i don't understand it.. I will have to look at this for awhile unless someone has a quicker way to explain how I add this to my project.. I just want all days before TODAY() grey background and option to add other specific dates that will get grey background – Glen Morse Aug 25 '23 at 18:28
-
I guess the one i need is for FMX.Calendar.pas Because i dont see a draw option in the source for TCalendar.pas – Glen Morse Aug 25 '23 at 19:26
-
Why use a `TStringGrid` for a calendar, instead of using [`TMonthCalendar`](https://docwiki.embarcadero.com/Libraries/en/Vcl.ComCtrls.TMonthCalendar)? It has an [`OnGetMonthBoldInfo`](https://docwiki.embarcadero.com/Libraries/en/Vcl.ComCtrls.TCommonCalendar.OnGetMonthBoldInfo) event for highlighting dates – Remy Lebeau Aug 25 '23 at 21:10