如何在Delphi的VCL TControlList中设置单个行的可变高度?
TControlList 实现可变行高的正确方案
问题根源
TControlList的ItemHeight是全局属性,作用是统一设置所有行的高度。在OnBeforeDrawItem事件中修改该属性会导致控件布局混乱——因为这个事件属于绘制阶段,此时控件已经完成了行布局计算,修改全局行高会让后续行的位置偏移,最终视图错乱。
正确实现方式
使用OnMeasureItem事件指定单行高度,这个事件在控件计算行布局前触发,能单独为每行设置高度且不会影响全局布局。
步骤1:绑定OnMeasureItem事件
在Delphi设计器中,为TControlList控件添加OnMeasureItem事件处理函数,代码如下:
procedure TForm9.ControlList1MeasureItem(AIndex: Integer; var AHeight: Integer); begin // 根据行索引设置对应高度 if AIndex = 3 then AHeight := 30 else AHeight := 70; end;
步骤2:优化OnBeforeDrawItem绘制逻辑
无需在OnBeforeDrawItem中修改ItemHeight,直接利用事件传入的ARect参数(该参数已根据OnMeasureItem设置的高度计算出当前行的绘制区域)完成内容绘制即可:
procedure TForm9.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas; ARect: TRect; AState: TOwnerDrawState); begin // 绘制背景 ACanvas.Brush.Color := IfThen(odSelected in AState, clHighlight, clWindow); ACanvas.FillRect(ARect); // 绘制行文本(垂直居中) ACanvas.Font.Color := clWindowText; DrawText(ACanvas.Handle, PChar('第' + IntToStr(AIndex + 1) + '行'), -1, ARect, DT_CENTER or DT_VCENTER or DT_SINGLELINE); end;
关键说明
OnMeasureItem是TControlList专门用于自定义行高的事件,通过修改AHeight参数为每行指定独立高度,控件会基于这些值完成正确的布局计算。- 务必避免在绘制阶段(如
OnBeforeDrawItem)修改全局的ItemHeight属性,这会打乱控件已完成的布局,导致视图错乱。
内容的提问来源于stack exchange,提问作者DarGra
相关产品推荐
相关产品推荐

