Delphi 控制';当显示另一个窗口时,SONEXIT会吃掉新控件的mouseup事件

Delphi 控制';当显示另一个窗口时,SONEXIT会吃掉新控件的mouseup事件,delphi,delphi-7,Delphi,Delphi 7,我在网上发现了这个问题 控件的OnExit在显示新控件时会吃掉mouseup事件 另一个窗口 这个问题很容易复制 在表格上放置3个TEDIT。在edit1中写入showmessage(“退出”) onexit事件运行程序给予edit1焦点使用鼠标给予 edit3焦点,单击“确定”以显示消息“观察您无法写入的方式” 现在编辑3中的任何内容,直到用鼠标单击 形态!设置edit2焦点,然后使用鼠标设置edit3焦点 观察如何在edit3中键入所需内容 到目前为止,我已经确定问题在于edit3 旧控件o

我在网上发现了这个问题

控件的OnExit在显示新控件时会吃掉mouseup事件 另一个窗口

这个问题很容易复制

在表格上放置3个TEDIT。在edit1中写入showmessage(“退出”) onexit事件运行程序给予edit1焦点使用鼠标给予 edit3焦点,单击“确定”以显示消息“观察您无法写入的方式” 现在编辑3中的任何内容,直到用鼠标单击 形态!设置edit2焦点,然后使用鼠标设置edit3焦点 观察如何在edit3中键入所需内容

到目前为止,我已经确定问题在于edit3 旧控件onExit事件时未收到mouseup消息 显示任何类型的窗口,我也尝试过显示 在onExit事件中我自己的形式,同样的结果。事实上,windows是 在这样的印象下,鼠标在edit3上按下 您已单击“确定”以显示消息

我想这是Delphi/Windows中的一个bug,但是如何解决它呢?我 知道我可以在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上的博客条目“”的“最佳实践”部分:

获取和/或丢失焦点时避免手动更改焦点。这 通常被证明是容易出错的


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

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

是,
(屏幕。)ActiveControl
将始终指向
Edit3
:在调用ShowMessage之前和之后:

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

但这只是为了回答您的问题!这当然不是提示或建议有关原因,请参阅Sertac的答案。

不要在OnExit事件处理程序中提供模式警告。将警告限制在视觉辅助设备上。如果需要显示模式警告,请在提交表单时显示(单击“确定”)。