我想创建一个字符串网格来显示某种垂直光标以突出显示当前选定的列.因此,在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;
Run Code Online (Sandbox Code Playgroud)
Delphi 7,Win XP
你正在做的没有错,你刚刚由VCL网格实现中的错误已经在德尔福4 VCL(我没有任何早期CD这里检查抓住了,但它甚至可能已经在16位的Delphi VCL已经)并且仍然在Delphi 2009中与我们合作.
使整个行或列无效的两种方法都是通过计算传递给内部InvalidateRect()方法的单元格区域来实现的.该区域始终以列/行0开头,并扩展到第一个完全不可见的行/列.很明显,这只能在未注册的客户区域正常工作.什么代码应该做的却是无效的最后一列/行,并让在代码InvalidateRect()助手找出哪些细胞确实可见,并计算出需要从该无效的客户区.
由于您正在编写自己的类,因此您可以轻松实现自己的方法来使正确的单元格范围无效; 多年前我做了同样的事情,还有更多的方法来使多列,多行和整个单元格块无效.由于InvalidateRect()是私人(伟大的思想也在场),你需要使用Windows API函数具有相同的名称,并计算矩形使用要么无效CellRect()或BoxRect()方法.
虽然InvalidateGrid()为你做的工作实在是一种大锤-它无效全格,我想这是不是你想要什么,当你开始使用InvalidateCol().
对于您的实验,您应该使每个单元的绘制周期容易看到.引起细胞的背景色在每次更新改变的是一个简单的方法来检查,你真的只能做小屏幕重绘.就像是
StringGrid1.Canvas.Brush.Color := RGB(Random(256), Random(256), Random(256));
StringGrid1.Canvas.FillRect(Rect);
Run Code Online (Sandbox Code Playgroud)
在OnDrawCell事件处理程序工作正常.
| 归档时间: |
|
| 查看次数: |
3816 次 |
| 最近记录: |