2011-08-26 29 views

Respuesta

11

Sí, puedes hacer esto. En primer lugar, usted tiene que inicializar el 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).

Luego simplemente tiene que responder a la notificación MCN_GETDAYSTATE. O puede crear su propio descendiente TDateTimePicker, o puede usar una 'clase de interceptor'.

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; 

Otro ejemplo: Supongamos que la pantalla actual se compone de tres meses, y que sólo desea seleccionar días en el 'mes que se muestra actualmente', es decir, en el mes medio. Suponga que desea que se seleccione cada tercer día, comenzando con un día seleccionado.

entonces usted desea utilizar los campos de bits

Month Bitfield 
0  00000000000000000000000000000000 
1  01001001001001001001001001001001 
2  00000000000000000000000000000000 

que son

Month Bitfield 
0  $00000000 
1  $49249249 
2  $00000000 

en hexadecimal. Así lo hace

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

Tenga en cuenta que esto solo funcionará en Windows Vista y posterior, p. ya que ['DTM_GETMCSTYLE'] (http://msdn.microsoft.com/en-us/library/bb761763 (VS.85) .aspx) se introdujo en Vista. –

+0

Supongo que el sistema operativo asigna y libera el búfer 'prgDayState' ... La documentación no es del todo clara en este punto. –

+1

Buen trabajo Andreas. –

4

OnGetMonthInfo evento mira BoldDays matriz para marcar días en un mes.

extraído de la ayuda:

Use BoldDays para codificar los días del mes en curso que debe aparecer en negrita. El valor devuelto por BoldDays se puede asignar al parámetro MonthBoldInfo de un controlador de eventos OnGetMonthInfo. Días es una matriz de enteros sin signo correspondientes a los días que deben ser negrita.

Búscalo en la ayuda.

Editar:

DateTimePicker.BoldDays es accesible.

OnGetMonthInfo está en desuso en Delphi XE, use OnGetMonthBoldInfo en su lugar. Aún no hemos descubierto la mejor manera de reintroducir el evento todavía.

Editar 2: Tuve un intento con la reintroducción del evento, pero parece que el mensaje de Windows no está vinculado en TDateTimePicker. Demasiado. Supongo que la solución de Andreas para ir directamente a la aplicación de mensaje de Windows es la mejor.

+0

Gracias por la respuesta; Realmente lo aprecio ... ¿Estás pensando en algo parecido a http: // stackoverflow.com/questions/4223237/bolddays-for-tdatetimepicker? –

+0

Esta respuesta se aplica a 'TMonthCalendar', y * not * a' TDateTimePicker'. –

+0

@Andreas, según la ayuda, TCommonCalendar (donde pertenece OnGetMonthInfo) es un miembro heredado de TDateTimePicker. –

Cuestiones relacionadas