How do you programmatically mark a date on a Delphi TDateTimePicker calendar?

When users click on the DateTimePicker configured for the drop-down calendar, I would like the different dates (selected using the code I created) to somehow stand out - color background, bold, color font, it does not matter. I just want certain dates to be marked .... How would I do this?

+6
source share
2 answers

Yes you can do it. First you must 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 just need to respond to the MCN_GETDAYSTATE notification. Either you can create your own TDateTimePicker descendant, or use the 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. Suppose that the current display consists of three months, and you want to select only days in the "current displayed month", that is, the average month. Suppose you want every third day to be selected starting from the selected day.

Then you want to use bit fields

 Month Bitfield 0 00000000000000000000000000000000 1 01001001001001001001001001001001 2 00000000000000000000000000000000 

that are

 Month Bitfield 0 $00000000 1 $49249249 2 $00000000 

in hexadecimal format. 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; 

Screen shot

+12
source

The OnGetMonthInfo event looks like a BoldDays array to mark days in a month.

Extracted from the help:

Use BoldDays to encode the days of the current month, which should be in bold. The value returned by BoldDays can be assigned to the MonthBoldInfo parameter of the OnGetMonthInfo event handler. Days is an array of unsigned integers corresponding to days that should be bold.

See it in the help.

Edit:

DateTimePicker.BoldDays is available.

OnGetMonthInfo is deprecated in Delphi XE, use OnGetMonthBoldInfo instead. However, the best way to resubmit the event has not yet been presented.

Edit 2: I really had time to reenter the event, but it seems that the Windows message is not related to TDateTimePicker. Very sorry. I guess the solution by Andreas heading straight for the window, the api message is the best.

+4
source

Source: https://habr.com/ru/post/896007/


All Articles