2011-08-26 23 views
6

Khi người dùng nhấp vào DateTimePicker, đặt để thả lịch, tôi muốn các ngày khác nhau (được chọn qua mã tôi tạo) để tô sáng theo cách nào đó - màu nền, phông chữ đậm, phông chữ màu, không quan trọng. Tôi chỉ muốn một số ngày nhất định được đánh dấu. ... Tôi sẽ làm như thế nào?Làm thế nào để bạn lập trình đánh dấu một ngày trong lịch TDateTimePicker của Delphi?

Cảm ơn, như mọi khi!

Trả lời

11

Có, bạn có thể thực hiện việc này. Trước tiên, bạn phải khởi tạo điều khiển:

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

Sau đó, bạn chỉ cần trả lời thông báo MCN_GETDAYSTATE. Hoặc bạn có thể tạo ra con cháu của riêng bạn TDateTimePicker hoặc bạn có thể sử dụng 'lớp ngăn chặn'.

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; 

Một ví dụ khác: Giả sử rằng màn hình hiện hành bao gồm ba tháng, và rằng bạn chỉ muốn chọn ngày trong 'tháng đang hiển thị', có nghĩa là, trong tháng giữa. Giả sử bạn muốn mỗi ngày thứ ba được chọn, bắt đầu với một ngày đã chọn.

Sau đó, bạn muốn sử dụng bitfields

Month Bitfield 
0  00000000000000000000000000000000 
1  01001001001001001001001001001001 
2  00000000000000000000000000000000 

Month Bitfield 
0  $00000000 
1  $49249249 
2  $00000000 

trong hệ thập lục phân. Vì vậy, bạn làm

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

Lưu ý rằng thao tác này sẽ chỉ hoạt động trên Windows Vista trở lên, ví dụ: vì ['DTM_GETMCSTYLE'] (http://msdn.microsoft.com/en-us/library/bb761763 (VS.85) .aspx) được giới thiệu trong Vista. –

+0

Tôi cho rằng hệ điều hành phân bổ và giải phóng bộ đệm 'prgDayState' ... Tài liệu chưa hoàn toàn rõ ràng về điểm này. –

+1

Làm việc tốt Andreas. –

4

OnGetMonthInfo sự kiện xem BoldDays mảng để đánh dấu các ngày trong một tháng.

Trích từ sự giúp đỡ:

Sử dụng BoldDays để mã hóa những ngày của tháng hiện tại sẽ xuất hiện in đậm. Giá trị trả về bởi BoldDays có thể được gán cho tham số MonthBoldInfo của trình xử lý sự kiện OnGetMonthInfo. Ngày là một mảng các số nguyên không dấu tương ứng với các ngày cần được in đậm.

Tra cứu trong trợ giúp.

Chỉnh sửa:

DateTimePicker.BoldDays có thể truy cập.

OnGetMonthInfo không còn được dùng trong Delphi XE, thay vào đó hãy sử dụng OnGetMonthBoldInfo. Vẫn còn havent đã tìm ra cách tốt nhất để giới thiệu lại sự kiện.

Chỉnh sửa 2: Tôi đã thực hiện việc giới thiệu lại sự kiện, nhưng có vẻ như thông báo cửa sổ không bị ràng buộc trong TDateTimePicker. Quá tệ. Tôi đoán giải pháp Andreas với việc đi thẳng tới cửa sổ thông báo api là tốt nhất.

+0

Cảm ơn đã phản ứng; Tôi thực sự đánh giá cao nó ... Bạn có đang nghĩ về một cái gì đó dọc theo dòng của http: // stackoverflow.com/questions/4223237/bolddays-for-tdatetimepicker? –

+0

Câu trả lời này áp dụng cho 'TMonthCalendar' và * không * cho' TDateTimePicker'. –

+0

@Andreas, theo trợ giúp, TCommonCalendar (nơi OnGetMonthInfo thuộc) là thành viên được thừa kế của TDateTimePicker. –

Các vấn đề liên quan