Winforms 如何制作无模式表单“块”?

Winforms 如何制作无模式表单“块”?,winforms,modal-dialog,Winforms,Modal Dialog,我有一个同时显示两个窗体/窗口的应用程序。第一个是用Form.Show方法显示的,因此它是非模态的,并且浮动到一边。第二个表单显示为form.ShowDialog,因此它是模态的,并且会阻塞 它阻塞的事实很重要,因为与第一个表单不同,第一个表单基本上只是装饰,第二个表单获取重要信息,所以我不希望我的程序在关闭之前继续运行 不幸的是,我现在需要允许用户与第一个表单进行一些有限的交互,能够调整它的大小,以及在显示第二个表单时进行其他轻微的视觉调整 显然,当第二个对话框处于模态时,这不起作用。因此,要

我有一个同时显示两个窗体/窗口的应用程序。第一个是用Form.Show方法显示的,因此它是非模态的,并且浮动到一边。第二个表单显示为form.ShowDialog,因此它是模态的,并且会阻塞

它阻塞的事实很重要,因为与第一个表单不同,第一个表单基本上只是装饰,第二个表单获取重要信息,所以我不希望我的程序在关闭之前继续运行

不幸的是,我现在需要允许用户与第一个表单进行一些有限的交互,能够调整它的大小,以及在显示第二个表单时进行其他轻微的视觉调整

显然,当第二个对话框处于模态时,这不起作用。因此,要么我需要找到一种方法,使第二个表单无模式,但在它打开时仍然阻塞……要么我需要使第一个表单在第二个表单以模态可见时以某种方式可访问


我是一名经验丰富的Java Swing程序员,但我对.NET窗体还是相当陌生的,所以这里可能有一个明显的答案我没有找到,只是因为我对.NET api不太熟悉?

我不相信你可以按照你要求的方式来做这件事。在不了解任何关于程序或表单的其他信息的情况下,我的最佳建议是修改表单,使您可以创建一个表单模式,或者想出一些机制来阻止用户在未完成当前模式表单中的所有必需信息的情况下继续操作

我在这里假设一下我要说的。。如果我错了,我会撤回这个,但我假设你有一个主窗体,你所说的两个窗体都是在主窗体中发生事件时显示的窗体。最后,我假设主表单中存在一些流程,如果没有表单A中所需的信息,这些流程将无法正确完成

假设是这种情况,表格A目前是模态形式,表格B是非模态形式,我建议采取以下措施:

在表单A中,添加一个公共布尔属性以跟踪是否已填写所有必需的信息。 更改表单A,使其不会使用ShowDialog打开,从而使其不是模态。这将允许与表格B交互 在表单A的OnClose事件中,检查所需信息是否已填写,如果未填写,则取消该事件。 在主窗体中,在适当的位置检查窗体A上的IsAllFilled属性以获取信息。如果ht为假,则再次显示表格A或重新聚焦 同样,我不确定您的要求,但您应该能够找到一些技巧来解决这个问题。我提供了前一篇文章,主要是为了让你的思想从盒子里流淌出来


尽管如此,更简单的方法是修改表单,使所有字段都位于模式表单上。

我不相信您可以按照要求的方式来完成此操作。在不了解任何关于程序或表单的其他信息的情况下,我的最佳建议是修改表单,使您可以创建一个表单模式,或者想出一些机制来阻止用户在未完成当前模式表单中的所有必需信息的情况下继续操作

我在这里假设一下我要说的。。如果我错了,我会撤回这个,但我假设你有一个主窗体,你所说的两个窗体都是在主窗体中发生事件时显示的窗体。最后,我假设主表单中存在一些流程,如果没有表单A中所需的信息,这些流程将无法正确完成

假设是这种情况,表格A目前是模态形式,表格B是非模态形式,我建议采取以下措施:

在表单A中,添加一个公共布尔属性以跟踪是否已填写所有必需的信息。 更改表单A,使其不会使用ShowDialog打开,从而使其不是模态。这将允许与表格B交互 在表单A的OnClose事件中,检查所需信息是否已填写,如果未填写,则取消该事件。 在主窗体中,在适当的位置检查窗体A上的IsAllFilled属性以获取信息。如果ht为假,则再次显示表格A或重新聚焦 同样,我不确定您的要求,但您应该能够找到一些技巧来解决这个问题。我提供了前一篇文章,主要是为了让你的思想从盒子里流淌出来


尽管如此,更简单的方法是只修改表单,使所有字段都位于模式表单上。

可以通过另一种方式进行修改,保持助手表单处于启用状态。然而,这需要一些技巧。ShowDialog方法调用迭代应用程序中的顶级窗口,并对其调用EnableWindow以禁用它们。您可以自己调用EnableWindow来撤消此操作。有一件事很棘手,那就是你不能显示对话框块。BeginInvoke可以解决这个问题。她 e是一个例子:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }
    protected override void OnLoad(EventArgs e) {
      mHelper = new Form2();
      mHelper.Show();
      mHelper.FormClosed += (s, ea) => mHelper = null;
    }
    Form2 mHelper;

    private void EnableForm2() {
      if (mHelper.IsHandleCreated) EnableWindow(mHelper.Handle, true);
    }
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool EnableWindow(IntPtr hWnd, bool enable);

    private void button1_Click(object sender, EventArgs e) {
      this.BeginInvoke(new Action(() => EnableForm2()));
      using (var dlg = new Form3()) {
        if (dlg.ShowDialog(this) == DialogResult.OK) {
          // etc...
        }
      }
    }
  }

这可以通过另一种方式来实现,保持助手窗体处于启用状态。然而,这需要一些技巧。ShowDialog方法调用迭代应用程序中的顶级窗口,并对其调用EnableWindow以禁用它们。您可以自己调用EnableWindow来撤消此操作。有一件事很棘手,那就是你不能显示对话框块。BeginInvoke可以解决这个问题。下面是一个例子:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }
    protected override void OnLoad(EventArgs e) {
      mHelper = new Form2();
      mHelper.Show();
      mHelper.FormClosed += (s, ea) => mHelper = null;
    }
    Form2 mHelper;

    private void EnableForm2() {
      if (mHelper.IsHandleCreated) EnableWindow(mHelper.Handle, true);
    }
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool EnableWindow(IntPtr hWnd, bool enable);

    private void button1_Click(object sender, EventArgs e) {
      this.BeginInvoke(new Action(() => EnableForm2()));
      using (var dlg = new Form3()) {
        if (dlg.ShowDialog(this) == DialogResult.OK) {
          // etc...
        }
      }
    }
  }

嗯……我找到了一种方法,通过在单独的线程上打开表单并调用Application.在这些线程上运行。但你在这里提出的建议给了我一个有趣的选择,让我可以玩玩!很好的方法。我有一个问题,你是如何将这种方法与Application.DoEvents方法相比较的?我知道一些我可以轻松处理的事情的危害,但我想知道上述方法是否可行better@nawfal读一读哦,亲爱的,3年半前我仍然用2个空格缩进代码。“时间过得真快!”杰里米·汤普森说,“是的,我做到了。我想我在上面的评论中暗示了这一点。不过还是要谢谢你。嗯……我找到了一种方法,通过在单独的线程上打开表单并调用应用程序来完成我想做的事情。在这些线程上运行。但你在这里提出的建议给了我一个有趣的选择,让我可以玩玩!很好的方法。我有一个问题,你是如何将这种方法与Application.DoEvents方法相比较的?我知道一些我可以轻松处理的事情的危害,但我想知道上述方法是否可行better@nawfal读一读哦,亲爱的,3年半前我仍然用2个空格缩进代码。“时间过得真快!”杰里米·汤普森说,“是的,我做到了。我想我在上面的评论中暗示了这一点。不过还是要谢谢你。