2011-08-26 16 views

risposta

11

Sì, puoi farlo. In primo luogo, si deve inizializzare il controllo:

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).

Quindi è sufficiente rispondere alla notifica MCN_GETDAYSTATE. O è possibile creare il proprio discendente TDateTimePicker oppure è possibile utilizzare una "classe intercettore".

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; 

Un altro esempio: Si supponga che la visualizzazione corrente è costituito da tre mesi, e che si desidera solo per selezionare giorni nel 'mese attualmente visualizzato', vale a dire, nel mese mezzo. Supponiamo che vogliate selezionare ogni terzo giorno, a partire da un giorno selezionato.

poi si desidera utilizzare i campi di bit

Month Bitfield 
0  00000000000000000000000000000000 
1  01001001001001001001001001001001 
2  00000000000000000000000000000000 

che sono

Month Bitfield 
0  $00000000 
1  $49249249 
2  $00000000 

in esadecimale. Così si fa

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; 

Screenshot http://privat.rejbrand.se/datetimepick.png

+5

Si noti che questo funzionerà solo su Windows Vista e versioni successive, ad es. poiché ['DTM_GETMCSTYLE'] (http://msdn.microsoft.com/en-us/library/bb761763 (VS.85) .aspx) è stato introdotto in Vista. –

+0

Suppongo che il sistema operativo allochi e liberi il buffer 'prgDayState' ... La documentazione non è completamente chiara su questo punto. –

+1

Bel lavoro Andreas. –

4

OnGetMonthInfo evento guarda all'array BoldDays per contrassegnare i giorni in un mese.

estratto dal aiuto:

Utilizzare BoldDays per codificare i giorni del mese in corso che dovrebbe apparire in grassetto. Il valore restituito da BoldDays può essere assegnato al parametro MonthBoldInfo di un gestore eventi OnGetMonthInfo. Days è una matrice di numeri interi senza segno corrispondenti ai giorni che dovrebbero essere in grassetto.

Cercare nell'aiuto.

Edit:

DateTimePicker.BoldDays è accessibile.

OnGetMonthInfo è obsoleto in Delphi XE, utilizzare invece OnGetMonthBoldInfo. Ancora non ha trovato il modo migliore per reintrodurre l'evento.

Modifica 2: Ho fatto un tentativo di reintrodurre l'evento, ma sembra che il messaggio di Windows non sia legato in TDateTimePicker. Peccato. Credo che la soluzione di Andreas con andare direttamente al messaggio di Windows API sia la migliore.

+0

Grazie per la risposta; Lo apprezzo davvero ... Stai pensando a qualcosa sulla falsariga di http: // StackOverflow.com/domande/4223237/bolddays-per-tdatetimepicker? –

+0

Questa risposta si applica a 'TMonthCalendar' e * not * a' TDateTimePicker'. –

+0

@Andreas, in base alla guida, TCommonCalendar (dove appartiene OnGetMonthInfo) è un membro ereditato di TDateTimePicker. –

Problemi correlati