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

sse*_*sse 5 delphi select selection tstringgrid

这是我之前的问题跟进 Delphi TStringGrid多选,确定有关Delphi String Grids的选定行.这是一个不同的问题.

我正在密切关注对象的ONSelectCell事件TSelectCellEvent =过程(Sender:TObject; ACol,ARow:Longint; var CanSelect:Boolean);

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

无论是否选择了一行或多行,ARow参数都会更新,但只有在我确定选择了一行且只有一行时,这才会对我有所帮助.

例如,如果它只是选中的一行,则使用Arow参数,如果有多行,则使用Selection.*属性来确定当前选择的行.

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

谢谢!

And*_*y M 6

我认为,部分问题在于所使用的术语。在您完全理解发生了什么之前,您一定会很困惑如何使用\xe2\x80\x98select\xe2\x80\x99来表示\xe2\x80\x98highlight\xe2\x80\x99\xe2\x80\ x98focus\xe2\x80\x99。在这种特殊情况下,两者之间应该有所区别。

\n\n

在继续之前,我希望您记住,焦点单元格也可以(并且实际上是)突出显示,但突出显示的单元格不一定是焦点单元格。

\n\n

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

\n\n

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

\n\n

现在说说我的要点。在调用相关处理程序时,永远Selection不准确,即它与传递给处理程序的&参数不相关。包含在调用处理程序之前突出显示的单元格范围,并且它在处理程序中永远不会自行更改。无论是一个单元格还是多个单元格,都保持不变,直到处理程序退出。当这种情况发生时(处理程序退出),就会发生变化(顺便说一句,结果取决于您是否重置)。AColARowSelectionSelection SelectionCanSelect

\n\n

因此,总而言之,您不能用来OnSelectCell确定Selection用户最近操作的实际结果。相反,我建议遵循@Sam \ 的建议并使用OnMouseUp*事件。它还允许您控制选择:如果您认为用户选择了\xe2\x80\x98太多\xe2\x80\x99,则可以更正最终范围。不过,在后一种情况下,我可能会考虑使用它OnMouseMove,因为它可以让您通过即时纠正范围 \xe2\x80\x98\xe2\x80\x99 来更平滑地响应。

\n\n

OnDrawCell看起来也不错,只要您只需要确定选择即可。

\n\n
\n\n

*根据您的评论,我必须补充一点,您还必须使用它OnKeyUp来处理使用键盘所做的选择。

\n


Sam*_*Sam 0

for RowIndex := StringGrid1.Selection.Top to StringGrid1.Selection.Bottom do
begin
  DoSomethingWithRow(RowIndex);
end;
Run Code Online (Sandbox Code Playgroud)

是的,我明白你的意思。似乎 Selection 属性在 OnSelectCell 事件之后更新,因此在事件内部只有旧值(即在 select 事件之前)。答案是将上面的代码移至 stringgrid 的 OnMouseUp 事件。看起来效果很好。