Delphi TStringGrid中单选择与多选择的检测

Delphi TStringGrid中单选择与多选择的检测,delphi,select,selection,tstringgrid,Delphi,Select,Selection,Tstringgrid,这是我之前关于Delphi字符串网格的问题的后续。这是另一个问题 我更仔细地观察了ONSelectCell事件 TSelectCellEvent=对象的过程(发送方:TObject;ACol,ARow:Longint;变量CanSelect:Boolean) 我注意到TStringGrid.Selection.Top和Bottom属性不一定准确(在事件本身中)。基本上,如果有人从选择多行变为仅选择一行,则selection.*属性不会更新,而如果有人选择多行,则会更新 无论选择了一行还是多行,A

这是我之前关于Delphi字符串网格的问题的后续。这是另一个问题

我更仔细地观察了ONSelectCell事件 TSelectCellEvent=对象的过程(发送方:TObject;ACol,ARow:Longint;变量CanSelect:Boolean)

我注意到TStringGrid.Selection.Top和Bottom属性不一定准确(在事件本身中)。基本上,如果有人从选择多行变为仅选择一行,则selection.*属性不会更新,而如果有人选择多行,则会更新

无论选择了一行还是多行,ARow参数都会得到更新,但这只有在我能够确定选择了一行且仅选择了一行时才有帮助

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

一定有更简单的方法

谢谢大家!

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

是的,我明白你的意思。似乎在OnSelectCell事件之后更新了Selection属性,因此在事件内部,您只有旧值(即,在SelectCell事件之前)。答案是将上面的代码移动到stringgrid的OnMouseUp事件。它似乎工作得很好。

我自己就能够解决这个问题,最后我将OnDrawCell事件与onSelectCell事件结合使用——我认为这将是一场混乱,但结果并不是那么糟糕

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

  • TStringGrid.Selection属性在OnDrawCell中始终是准确的
  • TStringGrid.Selection属性仅在选择了多行的OnSelectCell中准确

  • 公众的 previousHighlightCount:整数//标记以确保每行选择只调用onDraw中的必要代码一次。在onFormCreate中初始化为“1”。 程序Grid.OnDrawCell(…) 开始 ... SelectionCount:=Grid.Bottom-Grid.Top** 如果((SelectionCount=1)和(previousHighlightCount 1)),则 开始 GridUpdatedITS//为一行正确更新网格的例程。* 以前的HighlightCount:=1; 结束 其他的 previousHighlightCount:=prtedGrid.SelectionCount//用于倍增选定行的例程位于onSelectCell事件中,onSeelctCell用于多选。 .... 结束;

    感谢那些回应的人

    我认为,部分问题在于使用的术语。在您完全理解正在发生的事情之前,您一定很难理解“选择”是如何同时表示“突出显示”和“焦点”的。在这种特殊情况下,两者之间应该有所区别

    在我继续之前,我希望大家记住,聚焦单元格也可以(实际上)高亮显示,但高亮显示的单元格不一定是聚焦单元格

    现在,
    OnSelectCell
    事件与聚焦有关。单击单元格或尝试使用导航键在其上导航时,将触发处理程序。简而言之,当有人试图聚焦一个单元格时,就会调用处理程序。您可以通过重置
    CanSelect
    参数来禁止聚焦单元格(这同样意味着基本上可以聚焦,因为可以选择单元格,即高亮显示,而不聚焦,并且您无法使用
    OnSelectCell
    控制)

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

    现在谈谈我的主要观点。调用相关处理程序时,
    选择
    从不准确的,即它与传递给处理程序的
    ACol
    ARow
    参数不相关<代码>选择包含在调用处理程序之前高亮显示的单元格范围,并且它在处理程序中不会自行更改。无论是一个单元格还是多个单元格,
    Selection
    都保持不变,直到处理程序退出。当这种情况发生时(处理程序退出),
    Selection
    会发生变化(顺便说一下,结果取决于是否重置
    CanSelect

    因此,总之,您不能使用
    OnSelectCell
    来确定用户最近操作的实际
    选择。相反,我建议遵循的建议并使用
    OnMouseUp
    *事件。它还允许您控制选择:如果您认为用户选择了“太多”,您可以更正最终范围。在后一种情况下,我可能会考虑使用<代码> OnMuMeMooE>代码>,因为它允许您通过修改“飞行中的范围”来更顺利地进行响应。
    OnDrawCell
    只要您只需要确定选择,它似乎也很好



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

    StringGrid1.Selection.Top到StringGrid1.Selection.Bottom
    因为我正在使用onkeypress事件来选择/取消选择内容,所以它对我非常有效。

    我不知道你在问什么。“必须有一个更简单的方法”是一个问题吗?…必须有一个更简单的方法来知道在onSelectCell事件中选择了哪些行。@sse-您是如何解决这个问题的?谢谢,这是一个好主意,不幸的是,无法保证单元格将通过鼠标选择。我的另一个想法是跟踪选择。*在onDrawCell事件中,它总是准确的,但我也不喜欢这样,因为性能原因(以及 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;