delphi - 调用 InvalidateCol() 时 TStringGrid 不刷新

标签 delphi delphi-7

我想制作一个字符串网格来显示某种垂直光标以突出显示当前选定的列。因此,在 MouseDown 中,我调用 setCurPos,然后调用 InvalidateCol 以使当前列无效。这调用了 DrawCell。 DrawCell 将光标绘制在当前列上。

问题是这样的:如果我在网格中有更多行,那么它可以显示其中一些行将不可见(当然),因此网格的垂直滚动条将自动出现。当我向下滚动查看网格底部的行时,光标未绘制在这些行中。看起来未绘制光标的底部行数(现在在屏幕上可见)与网格顶部不可见行数成正比。

如果我最小化并恢复应用程序,光标就会很好地绘制。所以,显然 invalidateColumn() 不起作用。

procedure TmyGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
VAR aCol, aRow: Integer;
begin
 MouseToCell(X, Y, ACol, ARow);
 ...                                                                  
    inherited MouseDown(Button, Shift, X, Y); 
    CursorPosFocus:= ACol;                          
end;


procedure TmyGrid.setCurPos(CONST NewColumn: Integer);                 
VAR OldPos: Integer;
begin
 ...
 OldPos:= CursorPos;
 FCursorPos:= NewColumn;    
 ...
 //- This is not working:
 //InvalidateCol(OldPos);
 //InvalidateCol(NewColumn);    
 //Update;

 //- THIS WORKS:
 InvalidateGrid; 
end;


procedure TmyGrid.DrawCell(ACol, ARow: integer; ARect: TRect; AState: TGridDrawState);
Var TempRect: TRect;
begin
 inherited;
  ...

 {DRAW CURSOR}
 if CursorPos= ACol then
  begin
   TempRect.Top   := 0;
   TempRect.Left  := ARect.Left;
   TempRect.Right := ARect.Right;
   TempRect.Bottom:= ClientHeight-2;     
   Frame3D(Canvas, TempRect, $909090, $808080, 1);       
  end;
end;

Delphi 7、Win XP

最佳答案

你没有做错什么,你只是被 Delphi 4 VCL 中的 VCL 网格实现中的一个错误所捕获(我这里没有任何早期的 CD 可供检查,但它甚至可能已经存在于 Delphi 4 VCL 中) 16 位 Delphi VCL 已经存在)并且在 Delphi 2009 中仍然存在。

使整行或整列无效的两种方法都是通过计算传递给内部 InvalidateRect() 方法的单元格面积来实现此目的。该区域始终从第 0 列/行开始,并延伸到第一个完全不可见的行/列。很明显,这仅适用于未滚动的客户区域。代码应该做的是使最后一列/行无效,并让 InvalidateRect() 帮助器中的代码找出哪些单元格确实可见,并计算需要无效的客户区域那个。

由于您正在编写自己的类,因此您可以轻松地实现自己的方法来使正确的单元格范围无效;很多年前我也做了同样的事情,并使用了更多方法来使多列、多行和整个单元格无效。由于 InvalidateRect() 是私有(private)的(这也很棒),您需要使用同名的 Windows API 函数,并使用 CellRect() 计算要失效的矩形code> 或 BoxRect() 方法。

虽然 InvalidateGrid() 对你有用,但它实际上是一把大锤 - 它使整个网格无效,我认为这不是你开始使用 InvalidateCol( 时想要的) )

对于您的实验,您应该使每个单元格的绘制周期易于可见。使单元格的背景颜色随着每次更新而改变是一种简单的方法,可以检查您是否确实只进行了最少的屏幕重绘。类似的东西

StringGrid1.Canvas.Brush.Color := RGB(Random(256), Random(256), Random(256));
StringGrid1.Canvas.FillRect(Rect);

OnDrawCell事件处理程序中工作正常。

关于delphi - 调用 InvalidateCol() 时 TStringGrid 不刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3473305/

相关文章:

delphi - 如何在delphi7中处理unicode数据

delphi - 运算符不适用于该操作数类型 Delphi

delphi - 使用一些行颜色扩展 DBGrid

multithreading - 命名线程的最佳实践

delphi - 在 Delphi OLEDB 中加密 SQLite 数据库

delphi - 如何检查物体是否已经被破坏?

windows - 为什么Delphi主窗体WindowState在窗口最小化时返回 "wsNormal"?

delphi - Delphi 最好的报告组件?

delphi - 使用关联字符串(键/值)的最简单方法是什么?

windows - 如何取消延迟的 MoveFileEx 操作?