代码之家  ›  专栏  ›  技术社区  ›  Xanatos

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

  •  1
  • Xanatos  · 技术社区  · 16 年前

    我有一个同时显示两个窗体/窗口的应用程序。第一个是用form.show()方法显示的,所以它是无模式的,并飘到一边。第二个表单用form.showDialog()显示,因此它是模态的,并且它会阻塞。

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

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

    显然,当第二个对话框是模态的时,这不起作用。所以,要么我需要找到一种方法,使第二个窗体无模式,但在它打开时仍然被阻塞……要么我需要使第一个窗体在某种程度上可访问,而第二个窗体在模式上是可见的。

    我是一个有经验的JavaSwing程序员,但我对.NET窗体相当新,所以也许这里有一个明显的答案,我只是因为我对.NET API不太熟悉而失踪了。

    2 回复  |  直到 16 年前
        1
  •  4
  •   Hans Passant    16 年前

    这可以通过另一种方式来实现,保持helper表单处于启用状态。不过,这需要一些技巧。showDialog()方法调用迭代应用程序中的顶层窗口,并对它们调用enableWindow()以禁用它们。您可以自己调用enablewindown来撤消此操作。有一件事很棘手,那就是你不能,showDialog()块。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...
            }
          }
        }
      }
    
        2
  •  1
  •   David    16 年前

    我不相信你能按你要求的那样做。在不知道任何关于程序或表单的其他信息的情况下,我最好的建议是修改表单,以便您可以使一个表单成为模态,或者想出一些机制来阻止用户在不完成当前模态表单中的所有必需信息的情况下继续操作。

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

    假设情况是这样的,并且表格A当前是模态表格,表格B是非模态表格,我建议您执行以下操作:

    • 在表单A中,添加公共布尔属性以跟踪是否已填写所有必需的信息。
    • 更改窗体A,使其不使用showDialog()打开,因此它不是模态的。(这将允许与表格B进行交互)
    • 在表单A的onclosing事件中,检查所需信息是否已填写,如果未填写,则取消该事件。
    • 在主窗体中,检查属性以获取在窗体A上任何适当位置填写的信息。如果ht为false,则再次显示表单a(或重新聚焦)

    再说一次,我不确定你的要求,但你应该能找到一些技巧让你绕过这件事。我提供前一个主要是为了让你的想法流出盒子。

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