You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TCalendarView项角落绘制三角形:如何正确调用内部绘制方法?

解决TCalendarView先内部绘制再自定义图形的问题

你要实现先让TCalendarView完成内部绘制(包括文本、焦点、选中边框这些),再在奇数日期的角落画三角形,有两种靠谱的实现方式:

方法1:正确传入DoDrawItem的AController参数

CalendarViewViewInfo.DoDrawItem需要的AController参数,就是当前日历控件的Controller对象,直接从Sender转换获取即可:

procedure TfrmPreparation_order_Workload.CalendarDrawDayItem(Sender: TObject; DrawParams: TDrawViewInfoParams; CalendarViewViewInfo: TCellItemViewInfo);
var
  procedure DrawTriangle(ARectangle: TRect; ACanvas: TCanvas);
  var
    APoints: array [0..2] of TPoint;
  begin
    APoints[0] := ARectangle.Location;
    APoints[1] := Point(ARectangle.Location.x + 7, ARectangle.Location.y);
    APoints[2] := Point(ARectangle.Location.x, ARectangle.Location.y + 7);

    ACanvas.Pen.Color := clNavy;
    ACanvas.Brush.Color := clNavy;
    ACanvas.Polygon(APoints);
  end;
begin
  if Odd(CalendarViewViewInfo.Date.Day) then
  begin
    // 传入日历控件的Controller作为参数,执行单日历项的内部绘制
    CalendarViewViewInfo.DoDrawItem(DrawParams, TcxCustomCalendarController(TCalendarView(Sender).Controller));
    // 绘制自定义三角形
    DrawTriangle(DrawParams.DrawRect, DrawParams.Canvas);
    // 标记已处理,避免控件重复绘制
    DrawParams.Handled := True;
  end;
end;

方法2:调整绘制逻辑的执行顺序(更简洁)

不用手动调用DoDrawItem,先让控件完成内部绘制,再叠加自定义图形,最后标记已处理即可:

procedure TfrmPreparation_order_Workload.CalendarDrawDayItem(Sender: TObject; DrawParams: TDrawViewInfoParams; CalendarViewViewInfo: TCellItemViewInfo);
var
  procedure DrawTriangle(ARectangle: TRect; ACanvas: TCanvas);
  var
    APoints: array [0..2] of TPoint;
  begin
    APoints[0] := ARectangle.Location;
    APoints[1] := Point(ARectangle.Location.x + 7, ARectangle.Location.y);
    APoints[2] := Point(ARectangle.Location.x, ARectangle.Location.y + 7);

    ACanvas.Pen.Color := clNavy;
    ACanvas.Brush.Color := clNavy;
    ACanvas.Polygon(APoints);
  end;
begin
  if Odd(CalendarViewViewInfo.Date.Day) then
  begin
    // 临时取消已处理标记,让控件执行内部绘制
    DrawParams.Handled := False;
    TCalendarView(Sender).PaintTo(DrawParams.Canvas, DrawParams.DrawRect);
    // 叠加绘制三角形
    DrawTriangle(DrawParams.DrawRect, DrawParams.Canvas);
    // 重新标记已处理,防止重复绘制
    DrawParams.Handled := True;
  end;
end;

两种方法里,方法1更精准,因为DoDrawItem专门针对单个日历项执行内部绘制,不会影响控件其他区域。

内容的提问来源于stack exchange,提问作者Marc Guillot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 17:12:33