当显示另一个窗口时,Control的OnExit会在新控件上执行mouseup事件

时间:2011-08-16 14:37:16

标签: delphi delphi-7

我在Experts-Exchange上找到了这个问题。

  

Control的OnExit在显示时会为新控件执行mouseup事件   另一个窗口

     

问题可以很容易地复制。

     

在表单上放置3个tedits。在edit1中写一个showmessage('exit')   onexit事件运行程序给edit1焦点使用鼠标给出   edit3焦点,单击确定showmessage观察你怎么写不出来   现在编辑3中的任何内容,直到你用鼠标点击某处   形式!给edit2焦点,然后使用鼠标给予edit3焦点   观察如何在edit3中输入你想要的内容!

     

到目前为止,我已经确定问题在于edit3   当旧的控件onExit事件时,不会收到mouseup消息   显示任何类型的窗口,我也尝试过显示一个窗口   在onExit事件中我自己的形式,相同的结果。事实上,窗户是   在印象之后,鼠标在edit3之后被按下   你点击了Ok到showmessage

     

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

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

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

3 个答案:

答案 0 :(得分:6)

再次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;

一切都很好:)。

答案 1 :(得分:4)

我不太确定这种行为的原因是吃过的鼠标消息。无论如何,无论是否是这种情况,当您在控件的OnExit事件中激活窗口时,您正在做的是在焦点改变时更改焦点。这是因为,窗口在WM_SETFOCUS之前被激活,以便新聚焦的控件返回。不鼓励这样做,以下引用来自MSDN上的博客条目“Win32 Activation and Focus”的“最佳做法”部分:

  

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

由于激活窗口的模态特性,在焦点转移期间禁用控件的事实当然无济于事。如果你真的必须这样做,像Heinrich's answer这样的方法至少会延迟窗口的启动,直到焦点转移完成。

答案 2 :(得分:2)

  

在onexit事件中,我显示一个警告框,然后想要正常进行 - 将焦点移动到用户实际点击的位置。这可能吗?

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

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

但这只是为了你的问题的完整性!这当然不是小费也不是建议!请参阅Sertac的答案。