Как программно отметить дату в календаре TDateTimePicker в Delphi?
когда пользователи нажимают DateTimePicker, установите для выпадающего календаря, я хотел бы, чтобы различные даты (выбранные с помощью кода, который я создаю) были каким-то образом выделены-цветной фон, жирный шрифт, цветной шрифт, это не имеет значения. Я просто хочу отметить определенные даты. ... Как мне это сделать?
спасибо, как всегда!
2 ответов
Да, вы можете сделать это. Во-первых, вы должны инициализировать элемент управления:
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
).
тогда вы просто должны ответить на MCN_GETDAYSTATE
уведомления. Либо вы можете создать свой собственный TDateTimePicker
потомок, или вы можете использовать 'перехватчик класса'.
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;
другой пример: Предположим, что текущий дисплей состоит из трех месяцев и что вы хотите выбрать только дни в "текущем отображаемом месяце", то есть в среднем месяце. Предположить что вы хотите, чтобы каждый третий день был выбран, начиная с выбранного дня.
тогда вы хотите использовать bitfields
Month Bitfield
0 00000000000000000000000000000000
1 01001001001001001001001001001001
2 00000000000000000000000000000000
, которые
Month Bitfield
0 000000
1 249249
2 000000
в шестнадцатеричном виде. Так ты
for i := 0 to cDayState - 1 do
if i = 1 then
PMonthDayState(cardinal(prgDayState) + i*sizeof(TMonthDayState))^ := 249249
else
PMonthDayState(cardinal(prgDayState) + i*sizeof(TMonthDayState))^ := 000000;
OnGetMonthInfo событие выглядит на BoldDays массив для отметки дней в месяце.
извлечено из справки:
используйте BoldDays для кодирования дней текущего месяца, которые должны отображаться жирным шрифтом. Значение, возвращаемое BoldDays, может быть присвоено параметру MonthBoldInfo обработчика событий OnGetMonthInfo. Days-это массив целых чисел без знака, соответствующих дням, которые должны быть смелый.
посмотреть в справке.
Edit:
DateTimePicker.BoldDays доступен.
OnGetMonthInfo устарел в Delphi XE, вместо этого используйте OnGetMonthBoldInfo. Все еще не придумал лучший способ снова представить мероприятие.
редактирование 2 : Я действительно пошел с повторным введением события, но кажется, что сообщение windows не привязано к TDateTimePicker. Очень плохо. Я думаю, решение Andreas с переходом прямо к api сообщений windows является лучшим.