【问题标题】:DELPHI Edit.OnExit by TAB, show window result on focus bugDELPHI Edit.OnExit by TAB,在焦点错误上显示窗口结果
【发布时间】:2012-06-24 17:22:50
【问题描述】:

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

  • 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

我正在使用:

  • Delphi 7 企业版
  • Windows 7 x64

【问题讨论】:

    标签: delphi


    【解决方案1】:

    这是一个已知问题。当您在完成最后一次焦点更改之前更改焦点时,Windows 会出现问题(例如,焦点开始从 Edit1 更改为 Edit2,但 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 处理程序(这发生在响应 视窗 消息 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 处理程序中进行验证!

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-18
        • 1970-01-01
        • 1970-01-01
        • 2010-11-01
        • 1970-01-01
        • 2016-02-08
        相关资源
        最近更新 更多