在Delphi TStringGrid中检测单个或多个选择

这是对我之前的问题Delphi TStringGrid多选的后续,确定关于Delphi字符串网格的选定行。 这是一个不同的问题。

我正在更仔细地查看对象的ONSelectCell事件TSelectCellEvent = procedure(发件人:TObject; ACol,ARow:Longint; var CanSelect:Boolean);

我注意到TStringGrid.Selection.Top,Bottom属性不一定准确(在事件本身内)。 基本上,如果有人从选择多行到只有一行,选择。*属性不会得到更新,而如果选择多行,它们会。

无论是否选择了一行或多行,ARow参数都会得到更新,但如果我可以确定选择了一行并且只有一行,这只会对我有帮助。

例如,如果只选择了一行,则使用Arow参数,如果多于一行,则使用Selection。*属性确定当前选中的行。

必须有一个更简单的方法....

谢谢!


我认为,问题的一部分在于使用的术语。 在你完全理解正在发生的事情之前,必须弄清楚如何使用“选择”来表示'突出'和'重点'。 在这种特殊情况下,应该区分两者。

在我继续之前,我希望你记住聚焦的细胞也可以(并且实际上)突出显示,但突出的细胞不一定是聚焦的细胞。

现在, OnSelectCell事件与聚焦有关。 单击单元格时或当您尝试通过导航键在其上方导航时会触发该处理程序。 简而言之,当试图聚焦一个单元格时,调用处理程序。 您可以通过重置CanSelect参数来禁止聚焦细胞(这也意味着CanSelect ,因为单元格可以被选中,即突出显示,而不被聚焦,并且无法用OnSelectCell控制)。

另一方面, goRangeSelect选项和TDrawGrid.Selection属性与选择突出显示有关。 前者允许您(用户)突出显示多个单元格,而后者则指向突出显示的单元格的范围。

现在我的主要观点。 在调用处理程序时, Selection 永远不会准确,即与传递给处理程序的AColARow参数不相关。 Selection包含在调用处理程序之前突出显示的单元格区域,它在处理程序中始终不会自行更改。 无论是一个单元还是多个单元, Selection保持不变,直到处理程序退出。 正是这种情况发生时(处理程序退出) Selection发生变化(顺便说一下,结果取决于您是否重置CanSelect )。

因此,最后,您不能使用OnSelectCell来确定实际Selection是用户最近操作的结果。 相反,我会建议遵循@ Sam的建议并使用OnMouseUp *事件。 它还允许您控制选择:如果您认为用户选择了“太多”,则可以更正最终范围。 不过,在后一种情况下,我可能会考虑使用OnMouseMove ,因为它允许您通过“即时”更正范围来更顺利地做出响应。

OnDrawCell似乎也很好,只要你只需要确定选择。


*在您发表评论之后,我必须补充一点,您还必须使用OnKeyUp来处理使用键盘进行的选择。


for RowIndex := StringGrid1.Selection.Top to StringGrid1.Selection.Bottom do
begin
  DoSomethingWithRow(RowIndex);
end;

是的,我明白你的观点。 看来Selection属性是在OnSelectCell事件之后更新的,所以在事件中你只有旧值(即在选择事件之前)。 答案就是将上面的代码移动到stringgrid的OnMouseUp事件中。 它似乎工作正常。


我能够自己解决这个问题,我最终将OnDrawCell Event与onSelectCell Event结合使用 - 我认为这会变得很糟糕,但结果并不那么糟糕。

以下是我遇到同样问题的其他人的解决方案摘要。 以下是两个关键事实:

  • TStringGrid.Selection属性在OnDrawCell中总是精确的。
  • TStringGrid.Selection属性在OnSelectCell中是唯一准确的IFF多行已被选中。

  • public
      previousHighlightCount : integer; //flag to ensure that the necessary code within the onDraw only gets called once per row selection(s).  Initialize to '1' in onFormCreate.
    
    
    procedure Grid.OnDrawCell(...)
    begin
    ...
    SelectionCount := Grid.Bottom - Grid.Top;**
    if ((SelectionCount = 1) AND (previousHighlightCount  1)) then  
    begin                                                                               
       GridUpdateEdits;  //your routine to update the grid properly for one row.*    
       previousHighlightCount := 1;
    end
    else
      previousHighlightCount := PrtEdtGrid.SelectionCount;   //the routine for multiply selected rows is in the onSelectCell Event and onSeelctCell works for multiple selections.
    ....
    end;
    
    

    感谢那些回应!

    链接地址: http://www.djcxy.com/p/50627.html

    上一篇: Detecting single vs multiple selections in Delphi TStringGrid

    下一篇: How can I select multiple individual cells of a string grid?