TStringGrid 具有编辑和范围选择功能?
问题:
任何人都可以在任何地方指出一篇文章或代码示例来了解如何 在 TStringGrid 中提供编辑和范围选择?
是的,我知道有第三方网格可以做到这一点,但它是 令人沮丧的是内置网格缺乏这种基本功能。
背景:
期望能够编辑网格中的单元格是很正常的, 还可以选择一系列单元格,例如复制操作。
在交付时,TStringGrid 并没有这样做。这是非此即彼。事实上, 文档告诉我们有关网格选项的信息,“当 goEditing 包含在 选项,goRangeSelect没有效果”。
但是,看起来可能可以进行编辑和范围选择 无论如何在 TStringGrid 中!!!通过小心使用鼠标按下, mouseup、selectcell 和 exit 事件,您可以通过切换来关闭 在正确的时间打开和关闭编辑元素。但我还是没有 它完美,并且仅涵盖鼠标使用,而不涵盖键盘更改。
Question:
Can anyone point to an article or code samples anywhere on how to
provide BOTH editing AND range selection in a TStringGrid?
Yes, I KNOW there are third-party grids that do this, but it's
frustrating that the built-in grid lacks this basic capability.
Background:
It's pretty normal to expect to be able to both edit a cell in a grid,
and also to select a range of cells such as for a Copy operation.
As delivered, TStringGrid doesn't do that. It's either/or. In fact, the
docs tell us about the grid Options, "When goEditing is included in
Options, goRangeSelect has no effect".
However, it looks like it may be possible to do editing and rangeselects
in a TStringGrid anyway!!! Through careful use of the mousedown,
mouseup, selectcell and exit events, you can get dang close by switching
editing elements on and off at the right times. But I still don't have
it perfect, and that only covers mouse use, not keyboard changes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有为此使用过
TStringGrid
,所以我无法提供具体的答案。但是我假设您可以 手动(在代码中)启动正在编辑的单元格,这是正确的吗?该链接意味着即使网格的Options
中没有包含goEditing
也是可能的。 (如果情况并非如此,请参阅下文来解决此问题。)如果是这样,我建议采用以下方法:
组合选择和编辑行为
我发现这是一种很好的 Windows 标准行为方法:
离开网格处于选择模式,因此鼠标和键盘交互会选择单元格
根据某些条件触发您自己编辑的单元格(我认为您正在根据上一段中所说的内容来执行此操作。)是触发编辑的常见方法,以下标准是我的程序在与其他控件执行类似操作时遵循的标准:
选择正常。即单击选择、单击并拖动进行多选、使用键盘箭头和 Shift 或 Control 进行选择等。
当出现以下任一情况时,单元格进入编辑模式:
选择一个单元格,然后用户按
Enter
或F2
(F2
是标准的“重命名”或“编辑”快捷方式,适用于许多程序)用户在单元格上“缓慢双击”,即缓慢双击以选择和编辑,或在暂停后再次单击已选择的单元格。这模仿了资源管理器的行为,如果选择了一个文件并且稍后单击它,它将进入内联编辑/重命名模式。要实现此操作,请记录上次单击(并选择)单元格的时间。如果再次单击该单元格,并且时间大于
GetDoubleClickTime
然后他们缓慢地单击了两次,并进入编辑模式。这使您可以区分第一次单击选择、双击(执行某种操作)和缓慢的第二次单击进入编辑模式。我还倾向于检查鼠标位置,这样,如果缓慢双击一个对象并且没有首先选择该对象(即,这都选择了该对象,然后进入编辑模式),我会验证鼠标是否已“移动幅度很大。我使用
GetSystemMetrics
找到双击距离,并检查慢速双击是否在此框内。 (因为这不是真正的双击,所以我实际上检查了距离乘以2。我的操作代码是:const int iMAX_MOVE_AMOUNT = ::GetSystemMetrics(SM_CYDOUBLECLK) * 2;
(抱歉,C++ 不是 Delphi,但应该很容易转换!)但实际上我不确定这是否完全 100% 符合 Windows 准则。但在实践中,用户发现它的工作原理符合他们的预期。)
这应该让你在适当的时候在选择和编辑之间进行切换 。键盘和鼠标的时间。
其他想法
您可能会发现,通过子类化
TStringGrid
并创建一个新组件,其中一些更清晰、更容易实现。这将允许您在普通代码中实现这一点并覆盖内置行为(而不是事件处理程序),同时保持它对表单代码不可见。与仅通过OnMouseDown
等事件公开的方式相比,它还使您能够对鼠标事件或 Windows 消息进行较低级别的访问。最后,如果当Options
中包含goEditing
时显示编辑器出现问题,这将允许您更改该行为。如果您希望代码响应某些发生的事情,例如创建OnBeginEdit
事件,您也可以添加自己的事件。创建您自己的组件通常被视为高级 Delphi 主题,但实际上一旦您知道如何操作就非常容易! 这个网站有一些很好的主题,可以向您介绍该主题的总体情况,如果您走这条路并遇到问题,Stack Overflow 当然是一个不错的选择提问的地方 :) Embarcadero Delphi » VCL » 编写组件新闻组 /论坛也是一个很好的资源,事实上,对于这个特定主题来说,论坛甚至可能比 SO 更好。
希望有帮助!
I have not used the
TStringGrid
for this, so I can't provide a specific answer. But am I right in assuming you can manually (in code) start a cell being edited? That link implies it is possible even if the grid doesn't havegoEditing
included in itsOptions
. (See below to work around this if this is not true.)If so, I'd suggest the following approach:
Combined selection and edit behaviour
I find this is a good, Windows-standard-behaviour sort of approach:
Leave the grid in selection mode, so mouse and keyboard interaction selects cells
Trigger a cell being edited yourself, based on certain criteria (I think you are on the way to doing this from what you said in your last paragraph.) There are common ways to trigger editing, and the following criteria are what my programs follow when they do something similar with other controls:
Selection is normal. Ie, click to select, click and drag to multi-select, use the keyboard arrows and Shift or Control to select, etc.
A cell enters edit mode when either:
A cell is selected and the user presses
Enter
orF2
(F2
is the standard "Rename" or "Edit" shortcut, which works in a number of programs)The user "slow-double-clicks" on a cell - ie, slow-double-clicks to select and edit, or clicks again, after a pause, on an already-selected cell. This mimics Explorer's behaviour, where if a file is selected and you later click on it, it enters the inline edit/rename mode. To implement this, record when a cell was last clicked (and selected.) If it is clicked again, and if the time is greater than
GetDoubleClickTime
then they have clicked twice, slowly, and enter edit mode. This allows you to distinguish between the first click to select, a double-click (to perform some kind of action), and a slow second click, to enter edit mode.I also tend to check the mouse position, so that if an object is slow-double-clicked and it wasn't first selected (ie, this both selects the object and then enters edit mode) I verify the mouse hasn't moved very much. I use
GetSystemMetrics
to find the double-click distance, and check that the slow double click was within this box. (Because it's not a true doubleclick, I actually check the distance times 2. My action code is:const int iMAX_MOVE_AMOUNT = ::GetSystemMetrics(SM_CYDOUBLECLK) * 2;
(sorry, C++ not Delphi, but should be convertable easily enough!)but I'm actually not certain if this is completely and utterly 100% to Windows guidelines. In practice users find it works as they expect, though.)
That should let you change between selecting and editing at the appropriate times with both the keyboard and the mouse.
Miscellaneous thoughts
You may find some of this is cleaner and easier to implement by subclassing
TStringGrid
and creating a new component. That will allow you to implement this in normal code and override the inbuilt behaviour (rather than event handlers) while keeping it invisible to the form code. It will also give you lower-level access to the mouse events or Windows messages than are exposed simply through events such asOnMouseDown
. Finally, if there are problems with showing the editor whengoEditing
is included inOptions
, this will allow you to change that behaviour. You could also add your own events if you want your code to respond to certain things happening, such as creating anOnBeginEdit
event, say.Creating your own components is normally regarded as an advanced Delphi topic, but it's actually remarkably easy once you know how! This site has a few good topics that will introduce you to the subject in general, and if you go this route and encounter problems, Stack Overflow is of course a good place to ask questions :) The Embarcadero Delphi » VCL » Writing Components newsgroup / forum is also an excellent resource, in fact possibly even better than SO for this specific topic.
Hope that helps!
是的,这是旧帖子,但问题在 Delphi XE3 上仍然存在。
为了管理此功能,我在 SelectCell 过程中使用了下一个“技巧”:
<代码>
if (ARow = StringGridParam.Row) then
开始
StringGridParam.Options:= StringGridParam.Options + [goEditing] - [goRowSelect];
结束否则开始
StringGridParam.Options:= StringGridParam.Options + [goRowSelect] - [goEditing];
结束;
Yes it's old post, but the problem still exist on Delphi XE3.
To manage this feature I used next "trick" in SelectCell procedure :
if (ARow = StringGridParam.Row) then
begin
StringGridParam.Options:= StringGridParam.Options + [goEditing] - [goRowSelect];
end else begin
StringGridParam.Options:= StringGridParam.Options + [goRowSelect] - [goEditing];
end;