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

TGrid行颜色修改后滚动触发访问违规错误的解决咨询

问题分析与解决建议

核心问题原因

  1. 选中行状态不同步:手动维护FSelectedRow变量仅通过CellClick更新,无法响应键盘选中、滚动时行状态变化等场景,导致绘制时访问无效行数据。
  2. Bitmap访问不严谨:直接从Value中提取TBitmap未做有效性校验,滚动时Grid虚拟行复用可能导致Bitmap已被释放,触发内存访问错误。
  3. 代码结构不规范:过程内嵌套begin及变量声明位置易引发变量作用域或初始化问题。

修改步骤

1. 移除手动维护的选中行变量

删除private段的FSelectedRow: Integer;声明,同时简化RejestrCellClick事件:

procedure TZ.RejestrCellClick(const Column: TColumn; const Row: Integer);
begin
  Rejestr.SelectRow(Row);
  // 移除原FSelectedRow赋值和Repaint调用,Grid选中时会自动重绘
end;

2. 改用Grid自带的选中状态判断

修改RejestrDrawColumnCell和UstawWygladRejestru,通过State参数直接判断选中行:

procedure TZ.RejestrDrawColumnCell(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);
begin
  UstawWygladRejestru(Sender, Canvas, Column, Bounds, Row, Value, State);
end;

procedure TZ.UstawWygladRejestru(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);
var
  Bitmap: TBitmap;
  SourceRect: TRectF;
begin
  // 用Grid自带的选中状态判断,避免同步问题
  if State.Contains(TGridDrawState.Selected) then
    Canvas.Fill.Color := TAlphaColors.Bisque
  else
    Canvas.Fill.Color := TAlphaColors.Beige;

  Canvas.FillRect(Bounds, 0, 0, [], 1);

  if Column is TImageColumn then
  begin
    // 严格校验Bitmap有效性,避免访问已释放内存
    if Value.IsType<TBitmap> then
    begin
      Bitmap := Value.AsType<TBitmap>;
      if Assigned(Bitmap) and (Bitmap.Width > 0) and (Bitmap.Height > 0) then
      begin
        // 使用Bitmap实际尺寸作为源矩形,避免越界访问
        SourceRect := RectF(0, 0, Bitmap.Width, Bitmap.Height);
        Canvas.DrawBitmap(Bitmap, SourceRect, Bounds, 1, True);
      end;
    end;
  end
  else
  begin
    Canvas.Fill.Color := TAlphaColors.Black;
    Canvas.FillText(Bounds, Value.ToString, False, 1, [], TTextAlign.Leading, TTextAlign.Center);
  end;
end;

3. 可选:复用Grid默认图片绘制逻辑

如果不想手动处理Bitmap,可让Grid用原ImageStyle逻辑绘制图片,彻底避免内存管理问题:

procedure TZ.UstawWygladRejestru(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);
var
  NewState: TGridDrawStates;
begin
  if State.Contains(TGridDrawState.Selected) then
    Canvas.Fill.Color := TAlphaColors.Bisque
  else
    Canvas.Fill.Color := TAlphaColors.Beige;

  Canvas.FillRect(Bounds, 0, 0, [], 1);

  if Column is TImageColumn then
  begin
    // 移除选中状态,避免默认绘制覆盖自定义背景
    NewState := State - [TGridDrawState.Selected];
    // 调用Grid默认绘制逻辑处理图片
    (Sender as TGrid).DefaultDrawColumnCell(Canvas, Column, Bounds, Row, Value, NewState);
  end
  else
  begin
    Canvas.Fill.Color := TAlphaColors.Black;
    Canvas.FillText(Bounds, Value.ToString, False, 1, [], TTextAlign.Leading, TTextAlign.Center);
  end;
end;

额外注意事项

  • 确保Grid的RowSelect属性设为True,保证选中行状态正确传递。
  • 避免在DrawColumnCell中执行耗时操作,防止滚动卡顿。

内容的提问来源于stack exchange,提问作者Woj Tas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:35:07