如何检测用户何时完成 TStringGrid 单元格的编辑?
当用户完成输入数据时,我想返回字符串网格中单元格的内容。当用户按下键盘上的回车键或者单击或双击另一个单元格时,就完成了。
在Lazarus中有FinishedCellEditing的方法,但在Delphi中没有。我怎样才能在Delphi中检测到它?
I would like to return the contents of a cell in a string grid when the user finishes entering the data. The user is finished when pressing the enter key on the keyboard, or single- or double-clicking another cell.
In Lazarus there is a method of FinishedCellEditing, but not in Delphi. How can I detect it in Delphi?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我有完全相同的问题,但更简单的解决方案,因为我强制用户按 Enter 键...
技巧:我不会让用户在编辑单元格时更改到另一个单元格,所以我强制用户必须按 Intro/Enter 结束编辑,然后我允许更改为其他单元格。
不好的部分是 OnKeyPress 发生在 OnSetEditText 之前,所以我尝试使用 OnKeyUp...
我发现,在编辑单元格时,按 Enter/Intro 后,OnKeyUp 不会被触发...这是 VCL 上的一个 BUG。 .. 按键已被释放,但 OnKeyUp 尚未被触发。
所以,我做了另一个技巧来绕过这个......使用计时器来稍微改变我会做的事情,所以我让事件 OnSetEditText 之前被触发。
让我解释一下我已经成功做了什么...
我通过在 OnSelectCell 上放置代码来锁定选择另一个单元格,与此非常相似:
在 OnSetEditText 上我放置了这样的代码:
所以现在,需要的是检测用户何时按 Enter/Intro...我发现了一件可怕的事情,正如我所说的... OnKeyUp 不会因这样的键而被触发...所以,我将通过使用计时器和使用 OnKeyPress 来模拟它,因为 OnKeyPress 被触发,但是 OnKeyUp不,对于 Enter 键...
所以,在 OnKeyPress 上我放了类似的东西:
在这样的计时器事件上:
这有效,但我知道这很可怕,因为我需要使用计时器...但我不知道更好的方法...而且由于我需要不要让用户转到另一个单元格,而正在编辑的单元格没有有效值...我可以使用它。
到底为什么没有像 OnEndingEditing 这样的事件?
PD:我还注意到,对于每个按下的键,OnSetEditText 都会被触发多次,并且 Value 参数的值不同......至少在使用 OnGetEditMask 事件上设置的 EditMask 值“00:00:00”时。
I have quite the same problem, but easier solution since i force user to press Enter key...
The trick: I do not let the user change to another cell while is editing one, so i force user to must press Intro/Enter to end editing, then i allow to change to other cell.
The bad part is that OnKeyPress happens before OnSetEditText, so i tried with OnKeyUp...
And what i found is that just when editing a cell, after pressing Enter/Intro, OnKeyUp is not fired... that is a BUG on VCL... a key has being released and OnKeyUp has not being fired.
So, i make another trick to bypass that... use a Timer to differ what i would do just a little, so i let time to event OnSetEditText be fired before.
Let me explain what i have done to success...
I have locked selecting another cell by putting code on OnSelectCell, quite similar to this:
And on OnSetEditText i put code like this:
So now, what is needed is to detect when the user press Enter/Intro... and i found a horrible thing as i said... OnKeyUp is not fired for such key... so, i will simulate that by using a Timer and using OnKeyPress, because OnKeyPress is fired, but OnKeyUp not, for Enter key...
So, on OnKeyPress i put something like:
An on such timer event:
That works, but i know that is horrible because i need to use a Timer... but i do not know a better way... and since i need to not let user go to another cell while the one that is edinting does not have a valid value... i can use that.
Why on the hell there is not an event like OnEndingEditing?
P.D.: I have also noticed that OnSetEditText is fired multiple times for each key being pressed, and with different value on Value parameter... at least when working with EditMask value '00:00:00' set on OnGetEditMask event.
对于 VCL 的 TStringGrid,您需要 OnSetEditText 事件。但请注意,每次用户在任何单元格中更改某些内容时都会触发它。因此,如果您只想在用户完成编辑后执行某些操作,则必须观察事件参数的 row 和 col 值。当然,您需要注意用户结束编辑一个单元格并且不编辑另一个单元格时的情况,例如通过单击 TStringGrid 外部。像这样的东西:
With the VCL's TStringGrid you need the OnSetEditText event. Please note however that it fires everytime the user changes something in any cell. So, if you only want to do something after the user is finished editing, you will have to watch the row and col values of the event's parameters. And of course, you need to take care of the situation when a user ends editing a cell and does not edit another cell, for example by clicking outside the TStringGrid. Something like:
我通过响应发送到就地编辑器的 WM_KILLFOCUS 消息来做到这一点。我必须对就地编辑器进行子类化才能实现这一点。
我从 Raymond Chen 的博客中了解到,如果您随后执行改变焦点的验证,则这是不合适的。
I do this by responding to WM_KILLFOCUS messages sent to the inplace editor. I have to subclass the inplace editor to make this happen.
I understand from Raymond Chen's blog that this is not appropriate if you then perform validation that changes the focus.
这是最终版本...哇,我改进了自己的代码(我之前放的另一篇文章是我多年来一直使用的代码,直到今天...我看到了这篇文章,然后我放了我的代码...然后我尝试修复自己的代码,然后我得到了它,哇!我尝试了很多年,现在我终于得到了)。
这是相当棘手的,因为我到底如何想象可以在编辑器处于活动状态时选择一个单元格?
让我们看看如何做到这一点:
这对我来说就像一个魅力。
请注意,它需要两个变量来保存最后编辑的单元格坐标。
请记住,
Options
中的goEditing
必须为True
。请对另一篇文章感到抱歉...其他代码是我多年来使用的代码,因为我没有得到任何更好的解决方案...直到现在。
我希望这对其他人有帮助。
This is the final version... Wow, I improved my own code (the other post I put before was the code I was using for years until today... I saw this post and I put the code I had... then I tried to fix my own code and I got it, wow!, I was trying that for years, now I finally got it).
It is quite tricky since, how on the hell I could imagine a cell could be selected with editor active?
Let's see how to do it:
This works for me like a charm.
Please note it requires two variables to hold last edited cell coordinates.
Please remember
goEditing
must beTrue
inOptions
.Please sorry for the other post... that other code was the one I was using for years, since I did not get any better solution... until now.
I hope this helps others.
最好只使用 虚拟字符串网格 作为字符串网格Delphi 中的控件似乎并不能很好地支持这一点。
Its probably best to just use virtual string grid as the string grid control in Delphi does not really seem to support this very well.
解决方案:
SOLUTION:
基本上,用户可以通过多种方式结束编辑,但并非所有这些总是一个好的拦截点:
你需要问自己在什么情况下你想要更新内容。
例如:当用户取消模态表单或结束应用程序时,您是否想要更新它?
——杰罗恩
Basically, there are many ways a user can end editing, and not all these are always a good interception point:
You need to ask yourself under which circumstances you want to update the content.
For instance: do you want to update it, when the user cancels out of a modal form, or ends the application?
--jeroen
来自BCB 6的回答:
Answer from BCB 6: