【问题标题】:Switching modal forms in Delphi在 Delphi 中切换模态形式
【发布时间】:2014-05-08 00:50:47
【问题描述】:

我有一个模态形式 (A),它显示了另一个模态形式 (B)。 B 显示一个数据集并允许用户与之交互。我的问题是一个动作需要 A 再次成为焦点表单,这样用户就可以在不关闭 B 的情况下输入某些值。我尝试过 A.BringToFront 和 A.SetFocus,它确实显示在前面,但输入焦点仍然在 B当您单击不应单击的位置时,A 中的任何单击或类似操作都会导致窗口“叮”。代码有点像

A.ShowModal; . . .在 A 的事件中: B.ShowModal(); . . .在 B 的事件中:

someobject.someMethodThatRequiresAFocused;

我的猜测是,一些晦涩难懂的 API 调用可能会再次使 A 模态化 ¿ 有什么想法吗?

问候

【问题讨论】:

  • 唯一晦涩的就是你的代码 :-) 不,开个玩笑。但这就是模态的工作方式,以及为什么它被称为“模态”。你想要的是一个非模态窗口。
  • 为什么不把所有东西都放在一个表格上呢?您可以使用页面控件分隔部分。您甚至可以通过编程方式在页面之间翻页。

标签: delphi modal-dialog


【解决方案1】:

当显示模式表单时,所有当前可见的表单包括其他模式表单都被禁用。因此,不可能在多个模态形式之间切换。您需要重新考虑您的 UI 设计,以便 B 不会回到 A 以获得新的输入。至少,您可以让B 打开一个新的模态表单C,提示用户输入所需的值并将它们提供给B,然后BC 可以更新@987654328 @ 之后使用新值。

【讨论】:

    【解决方案2】:

    没有在窗口之间切换模式的 API。无论如何,您正在寻找您的案例的 API 是 EnableWindow。这就是模态的工作方式,用户应该使用的窗口以外的窗口被禁用,因此他/她无法与它们交互。这也是发出“叮”声的原因,向用户提供反馈。

    因此,虽然让用户使用已禁用的窗口转而使用另一个模式窗口在技术上很容易,但处理状态可能并不简单。我在下面提供了一个最低限度的示例,说明它似乎需要做什么。

    首先是'FormB'。假设您在 'FormA' 正在构造 'FormB' 时在 'Owner' 参数中传递了 'FormA' 的引用。以下是应该再次使“FormA”模态的代码可能如下所示:

    procedure TFormB.BtnMakeFormAModalAgainClick(Sender: TObject);
    begin
      Enabled := False;                  // so that 'A' will behave like it's modal
      EnableWindow(TFormA(Owner).Handle, True);  // so that 'A' could be interacted
      TFormA(Owner).SetFocus;
    end;
    

    当这段代码运行时,会发生什么情况是“FormA”被启用并被带到前面,而“FormB”被禁用——点击时会产生一个“叮当”。

    但我们还没有完成。因为我们修改了modality的含义——现在我们不希望'FormA'在用户完成后关闭。以下是 'FormA' 单元中的代码可能如下所示:

    type
      TFormA = class(TForm)
        BtnShowModalB: TButton;
        BtnOk: TButton;
        procedure BtnShowModalBClick(Sender: TObject);
        procedure BtnOkClick(Sender: TObject);
      private
        FModalB: TForm;
      end;
    
    implementation
    
    uses
      unitOfFormB;
    
    {$R *.dfm}
    
    procedure TFormA.BtnShowModalBClick(Sender: TObject);
    begin
      FModalB := TFormB.Create(Self);  // so that FormB can find FormA from the Owner
      FModalB.ShowModal;
      FModalB.Free;
      FModalB := nil; // Need this if we're going to decide if FormB is showing 
                      // by testing against this reference
    end;
    
    procedure TFormA.BtnOkClick(Sender: TObject);
    begin
      if Assigned(FModalB) then begin // is FormB the actual modal form?
        EnableWindow(Handle, False);  // disable this form so it would 'ding'
        FModalB.Enabled := True;      // enable FormB, so user can interact with it
        FModalB.SetFocus;
        ModalResult := mrNone;        // don't close, FormB is the first one to be closed
      end else
        ModalResult := mrOk;
    end;
    


    我几乎可以肯定这个示例并不完整,但这是您正在寻找的 API。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-26
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多