我在 Experts-Exchange 上发现了这个问题。
显示时控件的 OnExit 会占用新控件的 mouseup 事件
另一个窗口
这个问题很容易复制。
在表单上放置 3 个编辑。在 edit1 中写入 showmessage('exit')
onexit 事件 运行程序 给予 edit1 焦点 使用鼠标给予
edit3焦点,点击ok进入showmessage观察你怎么写不出来
现在编辑3中的任何内容,直到您用鼠标单击
形式 !给予 edit2 焦点,然后使用鼠标给予 edit3 焦点
现在就观察如何在 edit3 中输入您想要的内容!
到目前为止,我已经确定问题在于 edit3
旧控件 onExit 事件时未收到 mouseup 消息
显示任何类型的窗口,我也尝试过显示
我自己在 onExit 事件中的形式,结果相同。事实上,windows是
感觉鼠标在 edit3 上按住后
您已在显示消息中单击“确定”
我猜这是 Delphi/Windows 中的一个错误,但如何解决它?我
知道我可以在 edit3 的 onMouseDown 事件上强制 WM_LBUTTONUP (因为
它是该过程中调用的最后一个事件)但这不仅仅是
乏味,而且并不总是适用
我正在尝试做类似的事情:
在 onexit 事件中,我显示一个警告框,然后想要继续
像往常一样 - 将焦点移动到用户实际单击的位置。
这可能吗?
I found this question on Experts-Exchange.
Control's OnExit eats up mouseup event for new control when showing
another window
The problem can be replicated easily.
place 3 tedits on a form. write a showmessage('exit') in edit1's
onexit event run the program give edit1 focus use the mouse to give
edit3 focus, click ok to the showmessage observe how you can't write
anything in edit3 now, until you click with the mouse somewhere on the
form ! give edit2 focus, then use to the mouse to give edit3 focus
observe how you can type what you want in edit3 now !
So far I've established that the problem lies in the fact that edit3
doesn't receive a mouseup-message when the old controls onExit event
displays a window of any kind, i've tried it as well with showing a
form of my own in the onExit event, same result. In fact, windows is
under the impression that the mouse is held down over edit3 after
you've clicked Ok to the showmessage
I guess it's a bug in Delphi/Windows but how to work around it ? I
know i can force a WM_LBUTTONUP on edit3's onMouseDown event (since
its the last event called in the process) but that's more than
tedious, and not always applicable
I am trying to do something similiar:
In the onexit event I show a warningbox and then want to proceed
as normal - moving the focus to where the user in fact clicked.
Is that possible?
发布评论
评论(3)
PostMessage
再次来救援!将对话框延迟一段时间,以便 Windows 完成焦点更改。给自己发一条消息,而不是直接显示对话框:一切都很好:)
Once again
PostMessage
to the rescue! Defer your dialog just a little bit longer so that Windows can finish its focus change. Post yourself a message instead of showing the dialog directly:And everything is fine :)
我不太确定这种行为的原因是被吃掉的老鼠消息。无论如何,无论情况是否如此,当您在控件的 OnExit 事件中激活窗口时,您所做的就是在焦点更改时更改焦点。这是因为,在新获得焦点的控件返回之前,该窗口是在
WM_SETFOCUS
之前激活的。这是不鼓励的,以下引用来自“Win32 激活和焦点',MSDN 上的博客条目:由于激活窗口的模式性质,在焦点转移期间控件被禁用的事实当然不会有帮助。如果您确实必须这样做,请使用类似 Heinrich 的回答 至少会延迟窗口的启动,直到焦点转移完成。
I'm not so sure that the reason of the behavior is an eaten mouse message. Anyway, either that's the case or not, when you activate a window in an
OnExit
event of a control, what you're doing is, changing the focus while the focus is changing. That's because, the window is activated beforeWM_SETFOCUS
for the newly focused control returns. This is discouraged, the below quote is from 'Best practices' section of 'Win32 Activation and Focus', a blog entry on MSDN:The fact that the controls are disabled during focus transfer due to the modal nature of the activated window certainly would not help. If you really must do this, an approach like Heinrich's answer would at least delay the launch of the window till the focus transfer completes.
是的,
(Screen.)ActiveControl
将始终指向Edit3
: 在调用 ShowMessage 之前和之后:但这只是为了问题的完整性!这当然不是提示或建议!请参阅 Sertac 的回答了解原因。
Yes,
(Screen.)ActiveControl
will always point toEdit3
: before and after the call to ShowMessage:But this is just for completeness sake to your question! And it certainly is no tip nor advice! See Sertac's answer for the reason.