在Delphi中切换模态表单

时间:2014-05-08 00:50:48

标签: delphi modal-dialog

我有一个模态形式(A),显示另一种模态形式(B)。 B显示数据集并允许用户与其进行交互。我的问题是,一个动作要求A再次成为聚焦形式,这样用户可以输入某些值而不关闭B.我已经尝试了A.BringToFront和A.SetFocus它确实显示在前面,但输入焦点保留在B中当你点击不应该的地方时,A中的任何点击或类似物都会导致窗口“叮”。代码有点像

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

someobject.someMethodThatRequiresAFocused;

我的猜测是,一些模糊和奇怪的API调用可以再次使A模态¿任何想法?

此致

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

没有API可以在窗口之间切换模态。无论如何,您正在寻找案例的API是EnableWindow。这就是模态的工作原理,除了用户应该使用的窗口之外的窗口被禁用,以便他/她不能与它们交互。这也是'ding'声音的原因,为用户提供反馈。

因此,虽然让用户使用已禁用另一个模态窗口的窗口在技术上很容易,但处理状态可能不是直截了当的。我在下面提供一个最基本的例子,看看它似乎需要什么。

'FormB'首先。让我们假设您在'Owner'参数中传递'FormA'的引用,而'FormA'正在构建'FormB'。以下是应该使'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'被禁用 - 点击时会产生'ding'。

但我们还没有完成。因为我们已经修改了模态的含义 - 现在我们不希望在用户完成时关闭'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。