Delphi中模态形式的转换

Delphi中模态形式的转换,delphi,modal-dialog,Delphi,Modal Dialog,我有一个模态形式(a),它显示了另一个模态形式(B)。B显示数据集并允许用户与之交互。我的问题是,一个操作要求A再次成为焦点窗体,以便用户可以在不关闭B的情况下输入某些值。我尝试了A.BringToFront和A.SetFocus,它确实显示在前面,但输入焦点仍保留在B中,当您单击不应该单击的位置时,A中的任何单击或类似操作都会导致窗口“叮”。代码是怎样的 A.显示模态; . . . 在某个事件中: B.ShowModal(); . . . 在B事件中: 需要聚焦的someobject.some

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

A.显示模态; . . . 在某个事件中: B.ShowModal(); . . . 在B事件中:

需要聚焦的someobject.somemethods

我的猜测是,一些模糊而奇怪的API调用可能会再次生成一个模态?有什么想法吗


关于

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

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

没有在窗口之间切换模式的API。在任何情况下,您要查找的API都是
EnableWindow
。这就是模态的工作原理,除了用户应该使用的窗口之外,其他窗口都被禁用,因此用户无法与之交互。这也是“叮当”声的原因,以向用户提供反馈

因此,虽然让用户使用一个被禁用的窗口来使用另一个模式窗口在技术上很容易,但处理状态可能并不直接。我在下面给出了一个简单的例子来说明它的作用

首先是“表格B”。假设您在'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;
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;
当此代码运行时,所发生的情况是“FormA”被启用并放在前面,而“FormB”被禁用-当单击时将产生一个“叮”

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

没有API可以在windows之间切换模态。在任何情况下,您要查找的API都是
EnableWindow
。这就是模态的工作原理,除了用户应该使用的窗口之外,其他窗口都被禁用,因此用户无法与之交互。这也是“叮当”声的原因,以向用户提供反馈

因此,虽然让用户使用一个被禁用的窗口来使用另一个模式窗口在技术上很容易,但处理状态可能并不直接。我在下面给出了一个简单的例子来说明它的作用

首先是“表格B”。假设您在'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;
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;
当此代码运行时,所发生的情况是“FormA”被启用并放在前面,而“FormB”被禁用-当单击时将产生一个“叮”

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

唯一模糊的东西是你的代码:-)不,只是开玩笑。但这正是模态的工作原理,也是它被称为“模态”的原因。你想要的是一个非模态窗口。为什么不把所有的东西都放在一个窗体上呢?您可以使用pagecontrol分隔分区。你甚至可以通过编程在页面之间切换。唯一模糊的东西是在你的代码中:-)不,只是开玩笑而已。但这正是模态的工作原理,也是它被称为“模态”的原因。你想要的是一个非模态窗口。为什么不把所有的东西都放在一个窗体上呢?您可以使用pagecontrol分隔分区。您甚至可以通过编程方式在页面之间切换。