Delphi 10.2中TDBGrid的OnDrawColumnCell事件数据重叠问题求助
解决Delphi 10.2中TDBGrid OnDrawColumnCell事件数据重叠问题
我之前帮朋友排查过完全一样的问题,根源在于Delphi XE之后的TDBGrid组件在绘制机制上做了性能优化,和Delphi 7的老版本逻辑差异很大——当单元格获得焦点或者处于编辑状态时,默认的绘制流程不会被自定义的OnDrawColumnCell完全覆盖,就会出现新旧内容重叠的情况。
下面给你两种针对性的修复方案,结合你的场景给出具体代码:
方案一:自定义绘制前清空单元格区域
这是最直接的解决方式,在绘制自定义内容前,先用网格背景色填充单元格,彻底清除原有内容:
procedure TYourForm.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var CustomDisplayText: string; begin // 第一步:用网格默认背景色填充单元格,清除原有绘制内容 DBGrid1.Canvas.Brush.Color := DBGrid1.Color; DBGrid1.Canvas.FillRect(Rect); // 第二步:处理你的自定义显示逻辑(以LastName列为例) if Column.FieldName = 'LastName' then begin // 替换成你需要的自定义显示值 CustomDisplayText := '自定义前缀_' + Column.Field.AsString; // 绘制文本时添加少量偏移,避免贴边影响美观 DBGrid1.Canvas.TextOut(Rect.Left + 3, Rect.Top + 2, CustomDisplayText); end else begin // 其他列保持默认绘制逻辑 DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; // 可选:手动绘制选中/焦点单元格的边框,保持视觉一致性 if gdSelected in State then begin DBGrid1.Canvas.Brush.Color := clHighlight; DBGrid1.Canvas.FrameRect(Rect); end; end;
方案二:处理编辑状态的冲突(如果允许单元格编辑)
如果你的网格需要支持编辑,还需要避免编辑控件和自定义绘制的内容冲突:
- 把需要自定义显示的列的
ReadOnly属性设为True,禁止该列进入编辑状态; - 如果必须允许编辑,可以在
OnEditButtonClick事件中手动弹出编辑框处理,而不是依赖TDBGrid自动创建的编辑控件。
为什么Delphi 7中运行正常?
老版本的TDBGrid在触发OnDrawColumnCell事件时,会先完全清空整个单元格的绘制区域,自定义绘制的内容会直接覆盖所有原有元素;而Delphi 10.2这类新版本为了提升绘制性能,做了局部绘制的优化,只更新需要变化的部分,所以如果自定义绘制没有主动清空区域,就会和之前的内容重叠。
内容的提问来源于stack exchange,提问作者DelphiLearner




