When users click a DateTimePicker, set to drop down a calendar, I would like various dates (chosen via code I create) to highlighted in some way--colored background, bold font, colored font, it doesn't matter. I just want certain dates to be marked. ... How would I do this?
2 Answers
Yes, you can do this. First, you have to initialize the control:
const
DTM_GETMCSTYLE = DTM_FIRST + 12;
DTM_SETMCSTYLE = DTM_FIRST + 11;
...
SendMessage(DateTimePicker1.Handle,
DTM_SETMCSTYLE,
0,
SendMessage(DateTimePicker1.Handle, DTM_GETMCSTYLE, 0, 0) or MCS_DAYSTATE);
(uses CommCtrl
).
Then you simply have to respond to the MCN_GETDAYSTATE
notification. Either you can create your own TDateTimePicker
descendant, or you can use an 'interceptor class'.
type
TDateTimePicker = class(ComCtrls.TDateTimePicker)
protected
procedure WndProc(var Message: TMessage); override;
end;
...
procedure TDateTimePicker.WndProc(var Message: TMessage);
var
i: integer;
begin
inherited;
case Message.Msg of
WM_NOTIFY:
with PNMDayState(Message.LParam)^ do
if nmhdr.code = MCN_GETDAYSTATE then
begin
// The first visible day is SystemTimeToDateTime(stStart);
// cDayState is probably three, because most often three months are
// visible at the same time. Of course, the second of these is the
// 'currently displayed month'.
// Each month is represented by a DWORD (32-bit unsigned integer)
// bitfield, where 0 means not bold, and 1 means bold.
// For instance, the following code will select all days:
for i := 0 to cDayState - 1 do
PMonthDayState(Cardinal(prgDayState) + i*sizeof(TMonthDayState))^ := $FFFFFFFF;
end;
end;
end;
Another example: Assume that the current display consists of three months, and that you only want to select days in the 'currently displayed month', that is, in the middle month. Assume that you want every third day to be selected, starting with a selected day.
Then you want to use the bitfields
Month Bitfield
0 00000000000000000000000000000000
1 01001001001001001001001001001001
2 00000000000000000000000000000000
which are
Month Bitfield
0 $00000000
1 $49249249
2 $00000000
in hexadecimal. So you do
for i := 0 to cDayState - 1 do
if i = 1 then
PMonthDayState(cardinal(prgDayState) + i*sizeof(TMonthDayState))^ := $49249249
else
PMonthDayState(cardinal(prgDayState) + i*sizeof(TMonthDayState))^ := $00000000;

- 105,602
- 8
- 282
- 384
-
5Notice that this will only work on Windows Vista and later, e.g. since [`DTM_GETMCSTYLE`](http://msdn.microsoft.com/en-us/library/bb761763(VS.85).aspx) was introduced in Vista. – Andreas Rejbrand Aug 26 '11 at 22:41
-
I suppose that the operating system allocates and frees the `prgDayState` buffer... The documentation is not entirely clear on this point. – Andreas Rejbrand Aug 26 '11 at 22:46
-
Is it true thta the VCL's OnGetMonthInfo / OnGetMonthBoldInfo too work only on Vista and later (ie use the same DTM_GETMCSTYLE / DTM_SETMCSTYLE messages)? It isn't mentioned in the help... – ain Aug 27 '11 at 06:51
-
@ain, TMonthCalendar intercepts MCN_GETDAYSTATE and works for at least XP and up, but this interface was not implemented in the windows DateTimePicker. The DTM_GETMCSTYLE/DTM_SETMCSTYLE is not used in the current Delphi XE implementation. – LU RD Aug 27 '11 at 08:43
-
2Now why did I know the answer was by Andreas even before I got to the end? – Marjan Venema Aug 27 '11 at 08:43
-
It is very considerate that the `WM_NOTIFY` message in the case of a `MCN_GETDAYSTATE` notification is sent to the Date and Time Picker Control and not to the parent of the Month Calendar Control like it always [does](https://learn.microsoft.com/en-us/windows/desktop/controls/wm-notify). The actual parent of the Month Calendar is one of a "DropDown" class, the DropDown or the MonthCalendar has no window relation with the Date and Time Picker - no parentship, no ownership. I wonder what kind of trickery does the window manager play. Anyway, thanks for the code. – Sertac Akyuz Oct 26 '18 at 22:26
OnGetMonthInfo event looks at BoldDays array to mark days in a month.
Extracted from the help :
Use BoldDays to encode the days of the current month that should appear in bold. The value returned by BoldDays can be assigned to the MonthBoldInfo parameter of an OnGetMonthInfo event handler. Days is an array of unsigned integers corresponding to the days that should be bold.
Look it up in the help.
Edit :
DateTimePicker.BoldDays is accessible.
OnGetMonthInfo is deprecated in Delphi XE, use OnGetMonthBoldInfo instead. Still havent figured out best way to reintroduce the event yet.
Edit 2 : I did have a go with reintroducing the event, but it seems that the windows message is not tied in TDateTimePicker. Too bad. I guess Andreas solution with going straight to the windows message api is the best.

- 34,438
- 5
- 88
- 296
-
Thanks for the response; I really appreciate it ... Are you thinking of something along the lines of http://stackoverflow.com/questions/4223237/bolddays-for-tdatetimepicker? – Al C Aug 26 '11 at 21:49
-
This answer applies to `TMonthCalendar`, and *not* to `TDateTimePicker`. – Andreas Rejbrand Aug 26 '11 at 21:52
-
@Andreas, according to help, TCommonCalendar (where OnGetMonthInfo belongs) is an inherited member of TDateTimePicker. – LU RD Aug 26 '11 at 22:00
-
The OnGetMonthInfo event is introduced in `TCommonCalendar`, anchestor for both TMonthCalendar and TDateTimePicker - perhaps it is still possible to use it with TDateTimePicker? Althought the TDateTimePicker doesn't publish it... – ain Aug 26 '11 at 22:02
-
After some investigation it appears the OnGetMonthInfo event and DTM_GETMCSTYLE styles just will not work for the TDateTimePicker control in Windows XP. – AlainD Apr 02 '15 at 22:21