在 Delphi TStringGrid 中检测单选与多选
这是我上一个关于 Delphi 字符串网格的问题 Delphi TStringGrid 多重选择,确定选定行的后续问题。这是一个不同的问题。
我正在更仔细地研究 ONSelectCell 事件 TSelectCellEvent = 对象的过程 (Sender: TObject; ACol, ARow: Longint; var CanSelect: Boolean);
我注意到 TStringGrid.Selection.Top,Bottom 属性不一定准确(在事件本身内)。基本上,如果有人从选择多行变为仅选择一行,则 Selection.* 属性不会更新,而如果选择多行,则会更新。
无论是否选择一行或多行,ARow 参数都会更新,但只有当我可以确定选择了一行且仅选择了一行时,这才会对我有帮助。
例如,如果只选择了一行,则使用 Arow 参数,如果多于一行,则使用 Selection.* 属性来确定当前选择了哪些行。
一定有一个更简单的方法......
谢谢!
This is a follow up to my previous question Delphi TStringGrid multi select, determining selected rows regarding Delphi String Grids. It's a different question.
I was looking more closely at the ONSelectCell Event
TSelectCellEvent = procedure (Sender: TObject; ACol, ARow: Longint; var CanSelect: Boolean) of object;
I noticed that the TStringGrid.Selection.Top,Bottom properties are not necessarily accurate (within the event itself). Basically, if someone goes from selecting multiple rows to just one row, the selection.* properties do not get updated, whereas if one selects multiple rows, they do.
The ARow parameter does get updated regardless of whether one or more rows are selected, but this will only help me if I can determine that one and only one row was selected.
Eg, If it's just one row that was selected, then use Arow parameter, if more than one row then use Selection.* properties to determine which row(s) are currently selected.
There must be an easier way....
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为,部分问题在于所使用的术语。在您完全理解正在发生的事情之前,您一定会很困惑'select'如何同时表示'highlight'和'focus' >。在这种特殊情况下,两者之间应该有所区别。
在继续之前,我希望您记住,聚焦单元格也可以(并且实际上)突出显示,但是突出显示的单元格不一定是聚焦的一。
现在,
OnSelectCell
事件与聚焦有关。当单击单元格或尝试使用导航键在其上导航时,将触发该处理程序。简而言之,当尝试聚焦单元格时,就会调用处理程序。您可以通过重置CanSelect
参数来禁止聚焦单元格(这又意味着本质上CanFocus,因为单元格可以被选择,即突出显示,而没有集中注意力,并且您无法使用OnSelectCell
来控制它)。另一方面,
goRangeSelect
选项和TDrawGrid.Selection
属性与选择突出显示有关。前者允许您(用户)突出显示多个单元格,而后者则指向突出显示这些单元格的范围。现在说说我的要点。在调用有问题的处理程序时,
Selection
从不准确,即它与ACol
& 不相关。传递给处理程序的ARow
参数。Selection
包含在调用处理程序之前突出显示的单元格范围,并且它在处理程序内永远不会自行更改。无论是一个单元格还是多个单元格,Selection
都会保持不变,直到处理程序退出。当这种情况发生时(处理程序退出),Selection
就会发生变化(顺便说一句,结果取决于您是否重置CanSelect
)。因此,总而言之,您不能使用
OnSelectCell
来确定实际的选择
作为用户最近操作的结果。相反,我建议遵循 @Sam'的建议并使用OnMouseUp
* 事件。它还允许您控制选择:如果您认为用户选择“太多”,您可以更正最终范围。不过,在后一种情况下,我可能会考虑使用 OnMouseMove,因为它允许您通过“即时”修正范围来更平滑地响应。只要您只需要确定选择,
OnDrawCell
似乎也很好。*根据您的评论,我必须补充一点,您还必须使用
OnKeyUp
来处理使用键盘进行的选择。I think, part of the problem is in terminology used. Until you completely understand what is happening, it must be confusing to find how ‘select’ is used to mean both ‘highlight’ and ‘focus’. In this particular case there should be distinction between the two.
Before I proceed, I'd like you to keep in mind that the focused cell can also be (and actually is) highlighted, but a highlighted cell is not necessarily the focused one.
Now, the
OnSelectCell
event has to do with focusing. The handler is fired when the cell is clicked or when you are trying to navigate over it with navigation keys. In short, the handler is invoked when there's an attempt to focus a cell. You can prohibit focusing the cell by resetting theCanSelect
parameter (which, again, means essentially CanFocus, because the cell can be selected, i.e. highlighted, without being focused, and you can't control that withOnSelectCell
).The
goRangeSelect
option andTDrawGrid.Selection
property, on the other hand, have to do with selecting as highlighting. The former allows you (the user) to highlight more than one cell, while the latter points to the range of those cells highlighted.Now to my main point. Upon invoking the handler in question,
Selection
is never accurate, i.e. it is not correlated with theACol
&ARow
parameters that are passed to the handler.Selection
contains the range of cells that were highlighted just before calling the handler, and it never changes by itself within the handler. Whether one cell or more than one,Selection
stays the same until the handler exits. And it is when that happens (the handler exits) thatSelection
changes (and the result depends on whether you resetCanSelect
or not, by the way).So, in conclusion, you cannot use
OnSelectCell
to determine the actualSelection
as the result of the user's most recent action. Instead I would suggest following @Sam's advice and use theOnMouseUp
* event. It also allows you to have control over selection: you can correct the final range if you think the user has selected ‘too much’. In the latter case I would probably consider usingOnMouseMove
instead, though, as it allows you to respond more smoothly by correcting the range ‘on the fly’.OnDrawCell
seems fine too as long as you need just to determine the selection.*Following your comment, I must add, that you'd also have to employ
OnKeyUp
as well, to handle selections made with the keyboard.我能够自己解决这个问题,最后我将 OnDrawCell 事件与 onSelectCell 事件结合使用——我认为这会很混乱,但结果并没有那么糟糕。
这里总结一下我的解决方案,供遇到同样问题的其他人参考。以下是两个关键事实:
谢谢回复的人!!
I was able to solve this on my own, I wound up using the OnDrawCell Event in conjunction with onSelectCell Event -- which I thought was going to be a mess, but turned out not so bad.
Here's a summary of my solution for others who encounter the same problem. Here are two key facts:
Thanks to those who responded!!
是的,我明白你的意思。似乎 Selection 属性在 OnSelectCell 事件之后更新,因此在事件内部只有旧值(即在 select 事件之前)。答案是将上面的代码移至 stringgrid 的 OnMouseUp 事件。看起来效果很好。
Yes, I see your point. It seems the Selection property is updated after the OnSelectCell event so inside the event you only have the old values (ie. before the select event). The answer to that is to move the code above to the stringgrid's OnMouseUp event. It seems to work fine.
StringGrid1.Selection.Top 到 StringGrid1.Selection.Bottom
这对我来说非常有效,因为我使用 onkeypress 事件来选择/取消选择内容。
StringGrid1.Selection.Top to StringGrid1.Selection.Bottom
is what worked perfectly for me since I'm using the onkeypress event to select/deselect stuff.