Delphi 12.3中TCalendar组件如何同时高亮非连续单元格?
在Delphi 12.3中实现TCalendar多非连续日期高亮
可以实现,核心思路是利用TCalendar的OnDrawCell事件进行自定义绘制,同时维护一个存储需要高亮日期的集合。以下是具体实现步骤:
1. 准备日期存储集合
首先定义一个类级别的集合来保存需要高亮的日期,确保只存储日期部分(忽略时间):
uses System.Generics.Collections; type TForm1 = class(TForm) Calendar1: TCalendar; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Calendar1DrawCell(Sender: TObject; const ADate: TDateTime; const ARect: TRect; AState: TCalendarCellState); procedure Calendar1Click(Sender: TObject); private FHighlightedDates: TList<TDateTime>; function IsDateHighlighted(const ADate: TDateTime): Boolean; public end;
在窗体创建和销毁时初始化/释放集合:
procedure TForm1.FormCreate(Sender: TObject); begin FHighlightedDates := TList<TDateTime>.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin FHighlightedDates.Free; end;
2. 日期高亮判断方法
写一个辅助函数,判断当前单元格的日期是否在高亮集合中(仅比较日期部分):
function TForm1.IsDateHighlighted(const ADate: TDateTime): Boolean; var I: Integer; begin Result := False; for I := 0 to FHighlightedDates.Count - 1 do begin if Trunc(ADate) = Trunc(FHighlightedDates[I]) then begin Result := True; Break; end; end; end;
3. 自定义单元格绘制逻辑
在OnDrawCell事件中,对需要高亮的日期单独绘制背景和文本,其他日期使用默认绘制:
procedure TForm1.Calendar1DrawCell(Sender: TObject; const ADate: TDateTime; const ARect: TRect; AState: TCalendarCellState); var DateText: string; begin if IsDateHighlighted(ADate) then begin // 设置高亮背景色 Calendar1.Canvas.Brush.Color := $00FFE0C0; // 浅橙色,可自定义 Calendar1.Canvas.FillRect(ARect); // 设置高亮文本颜色 Calendar1.Canvas.Font.Color := clMaroon; // 居中绘制日期文本 DateText := DateToStr(ADate); Calendar1.Canvas.TextOut( ARect.Left + (ARect.Width - Calendar1.Canvas.TextWidth(DateText)) div 2, ARect.Top + (ARect.Height - Calendar1.Canvas.TextHeight(DateText)) div 2, DateText ); end else begin // 非高亮日期使用默认绘制逻辑 Calendar1.DefaultDrawCell(ADate, ARect, AState); end; end;
4. 添加用户交互(点击标记/取消高亮)
处理OnClick事件,让用户点击日期时切换其高亮状态:
procedure TForm1.Calendar1Click(Sender: TObject); var TargetDate: TDateTime; I: Integer; begin TargetDate := Trunc(Calendar1.Date); // 检查日期是否已高亮,是则移除 for I := 0 to FHighlightedDates.Count - 1 do begin if Trunc(FHighlightedDates[I]) = TargetDate then begin FHighlightedDates.Delete(I); Calendar1.Invalidate; // 刷新日历界面 Exit; end; end; // 未高亮则添加到集合 FHighlightedDates.Add(TargetDate); Calendar1.Invalidate; end;
额外提示
- 可根据需求修改高亮的背景色、文本色,甚至添加边框等视觉效果;
- 如果需要持久化高亮日期,可将集合中的日期保存到配置文件或数据库,启动时重新加载;
- 始终使用
Trunc处理日期,避免因TDateTime的时间部分导致匹配错误。
内容的提问来源于stack exchange,提问作者Moore
相关产品推荐
相关产品推荐

