No había visto este tema hasta ahora.
Para que el marcado de días sea consistente hay que crearse un componente o hacer un subclassing del TDateTimePicker. Si trabajasemos sobre un TMonthCalendar, bastaría con interceptar en el Formulario los mensajes WM_NOTIFY. Esto es debido a que un control windows envia las notificaciones a su parent, en el caso de TMonthCalendar las envía al Formulario pero en el caso de TDateTimePicker, lleva un MonthCalendar desplegable que notifica al DateTimePicker.
Se debe gestionar la notificación MCN_GETDAYSTATE de esta manera:
Código:
void __fastcall TForm1::SubClassTimePickerProc(TMessage& Message)
{
if(Message.Msg == WM_NOTIFY){
LPNMDAYSTATE PNMD = (LPNMDAYSTATE)Message.LParam;
if(PNMD->nmhdr.code == MCN_GETDAYSTATE){
// Poner en negrita del dia 1 al 25 del mes
for(int i = 0; i < PNMD->cDayState; i++){
DayStates[i] = 0;
for(int d = 1; d <= 25; d ++){
DayStates[i] |= (1 << (d - 1));
}
}
PNMD->prgDayState = DayStates;
Message.Result = 0;
}
}
OldTimePickerProc(Message);
}
He preparado un ejemplo con un TTimePicker y un TMonthCalendar para ver las diferencias. Ambor marcan del dia 1 al 25 de cada mes.
Código:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
//---------------------------------------------------------------------------
typedef void __fastcall(__closure *PWndProc)(Messages::TMessage &Message);
class TForm1 : public TForm
{
__published: // IDE-managed Components
TDateTimePicker *DateTimePicker1;
TMonthCalendar *MonthCalendar1;
private: // User declarations
PWndProc OldTimePickerProc;
MONTHDAYSTATE DayStates[12]; // debe vivir mientras el popup esté abierto
void __fastcall WMNotify(TMessage &Message);
void __fastcall SubClassTimePickerProc(TMessage& Message);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_NOTIFY, TMessage, WMNotify)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Código:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define DTM_GETMCSTYLE (DTM_FIRST + 12)
#define DTM_SETMCSTYLE (DTM_FIRST + 11)
TForm1 *Form1;
//---------------------------------------------------------------------------
void __fastcall SetSubCass(TWinControl *WC, PWndProc newProc, PWndProc *oldProc)
{
*oldProc = WC->WindowProc;
WC->WindowProc = newProc;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
DWORD style = SendMessage(DateTimePicker1->Handle, DTM_GETMCSTYLE, 0, 0);
SendMessage(DateTimePicker1->Handle, DTM_SETMCSTYLE, 0, style | MCS_DAYSTATE);
SendMessage(MonthCalendar1->Handle, DTM_SETMCSTYLE, 0, style | MCS_DAYSTATE);
SetSubCass(DateTimePicker1, SubClassTimePickerProc, &OldTimePickerProc);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMNotify(TMessage &Message)
{
LPNMDAYSTATE PNMD = (LPNMDAYSTATE)Message.LParam;
if(PNMD->nmhdr.code == MCN_GETDAYSTATE){
for(int i = 0; i < PNMD->cDayState; i++){
DayStates[i] = 0;
// Poner en negrita del dia 1 al 25 del mes
for(int d = 1; d <= 25; d ++){
DayStates[i] |= (1 << (d - 1));
}
}
PNMD->prgDayState = DayStates;
Message.Result = 0;
}
else{
// Deja que VCL procese el resto de notificaciones normalmente
TForm::Dispatch(&Message);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SubClassTimePickerProc(TMessage& Message)
{
if(Message.Msg == WM_NOTIFY){
LPNMDAYSTATE PNMD = (LPNMDAYSTATE)Message.LParam;
if(PNMD->nmhdr.code == MCN_GETDAYSTATE){
// Poner en negrita del dia 1 al 25 del mes
for(int i = 0; i < PNMD->cDayState; i++){
DayStates[i] = 0;
for(int d = 1; d <= 25; d ++){
DayStates[i] |= (1 << (d - 1));
}
}
PNMD->prgDayState = DayStates;
Message.Result = 0;
}
}
OldTimePickerProc(Message);
}
Saludos.