控件的 OnExit 在显示另一个窗口时会占用新控件的鼠标向上事件



我在expert - exchange上发现了这个问题。

控件的OnExit在显示新控件时占用mouseup事件另一个窗口

这个问题很容易重复。

在表单上放置3个元素。在编辑1中写入showmessage('exit')Onexit事件运行程序给edit1焦点用鼠标给编辑3的焦点,点击确定到showmessage观察你如何不能写现在在edit3中的任何东西,直到你用鼠标点击某个地方形式!给edit2焦点,然后使用鼠标给edit3焦点看看你现在如何在edit3中输入你想要的东西!

到目前为止,我已经确定问题在于编辑3当旧的控件onExit事件发生时,不会收到鼠标提示信息显示任何类型的窗口,我也尝试过显示一个在onExit事件中我自己的表单,结果相同。事实上,窗户是给人的印象是鼠标被按在编辑3之后单击showmessage

的Ok

我猜这是一个错误在Delphi/Windows,但如何解决它?我我知道我可以强制在edit3的onMouseDown事件WM_LBUTTONUP(因为它是进程中调用的最后一个事件),但这不仅仅是乏味,并不总是适用

我正在尝试做类似的事情:

在onexit事件中,我显示一个警告框,然后想要继续像往常一样——把焦点移到用户实际点击的地方。这可能吗?

PostMessage再一次救援!将对话框推迟一点,以便Windows可以完成焦点更改。发布你自己的消息,而不是直接显示对话框:

const
  WM_SHOWMYDIALOG = WM_APP + 321;
TForm1 = class(TForm)
  Edit1: TEdit;
  Edit2: TEdit;
  procedure Edit1Exit(Sender: TObject);
private
  procedure WMSHOWMYDIALOG(var Message: TMessage); message WM_SHOWMYDIALOG;
end;
procedure TForm1.Edit1Exit(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_SHOWMYDIALOG, 0, 0);
end;
procedure TForm1.WMSHOWMYDIALOG(var Message: TMessage);
begin
  ShowMessage('Nice one');
end;

一切都很好

我不确定这种行为的原因是吃老鼠的消息。不管怎样,不管是不是这样,当你在控件的OnExit事件中激活一个窗口时,你所做的是,在焦点改变的同时改变焦点。这是因为,窗口在WM_SETFOCUS为新聚焦控制返回之前被激活。这是不鼓励的,以下引用来自MSDN上的一篇博客文章"Win32激活和焦点"的"最佳实践"部分:

当获得和/或失去焦点时,避免手动改变焦点。这通常被证明容易出错。


由于激活窗口的模态性质,控件在焦点转移期间被禁用的事实肯定不会有帮助。如果您确实必须这样做,那么像Heinrich的答案这样的方法至少可以延迟窗口的启动,直到焦点转移完成。

在onexit事件中,我显示了一个警告框,然后希望像往常一样继续-将焦点移动到用户实际单击的位置。这可能吗?

是的,(Screen.)ActiveControl将始终指向Edit3:在调用ShowMessage:

之前和之后
procedure TForm1.Edit1Exit(Sender: TObject);
begin
  ShowMessage('Exit');
  PostMessage(ActiveControl.Handle, WM_LBUTTONUP, 0, 0);
end;

但这只是为了完整地回答你的问题!这当然不是小费或建议!参见Sertac的答案

最新更新