1

我在以下情况下遇到问题:

  • 2 编辑
  • 在 Edit1 中键入内容并按 TAB,焦点转到 Edit2
  • Edit1.OnExit -> 显示带有消息“处理中...”的表单(进行冗长的验证)

表单关闭后,Edit2 上的焦点似乎“崩溃”了...... - Edit2 中的孔 TEXT 未选中 - carret 没有闪烁

例子:

  • 创建一个新表格
  • 进行 2 次编辑
  • 在 Edit1 中将此设置为 OnExit 事件:

    procedure TForm1.Edit1Exit(Sender: TObject);
    begin
      with TForm.CreateNew(self) do
         try
           Width := 100;
           Height := 50;
           Position := poMainFormCenter;
           show;
           sleep(200);
         finally
           Free;
         end;
    end;
    
  • 运行应用程序

  • 在 Edit1 中设置焦点并按 TAB

我在用着:

  • 德尔福 7 企业版
  • 视窗 7 x64
4

2 回答 2

3

这是一个已知问题。当您在完成最后一次焦点更改之前更改焦点时,Windows 会出现问题(例如,焦点开始从 更改Edit1Edit2,但Edit1.OnExit会执行一些操作以将焦点更改为另一个控件或表单。

例如,当应用程序尝试在OnExit事件中进行验证,然后在验证失败时尝试将焦点返回到原始控件时,就会发生这种情况。

最简单的解决方案是向您的表单句柄发布消息OnExit,并在那里处理焦点更改需求。一旦目标控件获得输入焦点,它将触发,Windows 不会感到困惑。

const
   UM_EDIT1_EXITED = WM_USER + 1;

type
  TForm1=class(TForm)
  ...
  private
    procedure UMEdit1Exited(var Msg: TMessage); message UM_EDIT1_EXITED;
  end;

implementation

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  PostMessage(Handle, UM_EDIT1_EXITED, 0, 0);
end;

procedure TForm1.UMEdit1Exited(var Msg: TMessage);
begin
  // Show your other form here
end;

来自TeamB的 Peter 博士的旧 Borland NG 帖子:

这是我关于“从 OnExit 显示对话框”问题的一般布道:

如果触发了 OnExit 处理程序(这发生在响应 Windows 消息 WM_KILLFOCUS),则 Windows 处于焦点更改之中。如果您在处理程序中执行导致另一个焦点更改的操作(例如弹出消息框或执行 SetFocus 调用),Windows 会非常混乱。缺少的光标就是一个症状。

如果您必须从 OnExit 处理程序向您的用户显示消息,请这样做:

  1. 在单元的接口部分的某处为用户消息定义一个常量,在表单的类型声明上方

    '常量 UM_VALIDATE = WM_USER + 200;'

  2. 为您的表单提供此消息的处理程序,最好放在类声明的私有部分:

    Procedure UMValidate( Var Msg: TMessage ); message UM_VALIDATE;

  3. 如果字段的内容不正确,则从 OnExit 处理程序向表单发布 UM_VALIDATE 消息。您可以在消息的 wparam 和 lparam 参数中传递附加信息,例如错误号和 Sender 对象。事实上,您可以在 UMValidate 处理程序中进行整个验证!

于 2012-06-22T14:19:33.400 回答
2

我不确定这里到底发生了什么,但看起来消息的处理顺序有点混乱。而不是杀死你的其他形式Free,使用Release和焦点将按照你的意愿行事。

另一种选择是使用ShowModal而不是Show. 通常,您会以模态方式显示处理对话框,因为您不希望用户在处理时对主表单进行修改。如果你这样做,那么你可以继续使用Free.

于 2012-06-22T12:02:44.740 回答