【问题标题】:Owner of Form which is not inside Application.Run不在 Application.Run 中的 Form 的所有者
【发布时间】:2013-12-10 12:16:34
【问题描述】:

我试图在应用程序启动之前显示一个表单并获取它的DialogResult,所以我只是创建它并使用ShowDialog(因为Application.Run 的返回值是无效的)。

我担心的是它可能会被当时可能显示的其他表单错误地“劫持”。显然,不是通过这个应用程序。参见What is the meaning of Form.Show(null)?,不建议使用ShowDialog 的无参数重载。

我已经测试并看到表单的Owner 属性为空。但会一直如此吗?或者我应该创建一个表单并将其用作所有者而不显示它?这似乎是一个奇怪的解决方案,但从逻辑上讲它应该避免任何问题。还是会推出新的?

【问题讨论】:

  • 被应用中的表单劫持?如何? Application.Run 尚未运行...
  • 你能提供一个你害怕的场景吗?
  • @rene 正如我所说的“显然不是这个应用程序”。
  • @Sinatr 在特定情况下在另一个模态对话框上显示模态对话框时,我已经遇到过这个问题,并且对话框意外关闭。我不记得确切的细节。我花了很长时间才发现问题。从那时起 - 我总是指定所有者。
  • 您不能获取桌面窗口并作为所有者提供它吗?

标签: c# winforms forms


【解决方案1】:

显然不是这个应用程序

Windows 已经解决了这个问题,它强制将进程和线程拥有的窗口严格分开。例如,对话框所有者的典型选择是 GetActiveWindow() 返回的窗口。活动窗口是 thread 的一个属性。例如,这解释了为什么从工作线程发出的 MessageBox.Show() 调用永远不会对其余窗口产生模态。

针对另一个进程的窗口创建一个窗口模式在技术上是可行的,但需要大量的努力。该应用程序必须调用 AttachThreadInput(),这是一个非常简单的 winapi 函数,没有人会意外调用它。也是死锁的重要来源。

除非你在索马里海岸附近的船上编程,否则没有理由担心你的窗户被劫持。

【讨论】:

  • 谢谢。​​​​​​​​​​​​​​​​​​​​​​​​​​还有:)@索马里海岸。
【解决方案2】:
[STAThread]
        static void Main()
        {
            Form1 form1 = new Form1();
            //here I  suppose the form you want to show  
            Form1 form2 = new Form2();
            form2.ShowDialog(form1);  

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(form1);
        }

【讨论】:

  • 是的。我在我的问题中提到了这个选项 - Or should I create a Form and use that as the Owner without showing it? 但这是我的问题 - 这真的需要吗? (这可能不会引入任何微妙的错误吗?-因为它有点不合逻辑。)
  • AFAIK 最适合您的情况
【解决方案3】:

基本上,当此窗口没有父级时,您使用ShowDialog()。通常这发生在主窗口。如果你一个接一个地打开一个窗口,而关闭前一个窗口,那么会有多个ShowDialog()s。

如果您正在显示 dialog(这也是一个窗口),那么您可以指定它的父级以实现某种行为。例如,当 alt-tabbing 到那个窗口时,它的对话框将显示在前面。将此视为建立亲子关系。

我不知道这种情况,当多个表单声明同一父级时。但这听起来像是一个明显的错误,例如:

 public Form1 FormMain = new Form1();
 ...
 // show main form
 FormMain.ShowDialog();
 ...
 // somewhere in the main form - show dialog
 Form2 form2 = new Form2();
 form2.ShowDialog(FormMain);
 ...
 // somewhere in form2 - show dialog
 Form3 form3 = new Form3();
 form3.ShowDialog(FormMain); // wrong, should be form2!

【讨论】:

    【解决方案4】:

    这没有经过测试,因为我无法重新创建父级除了null(即对第三方非托管父级的引用)之外的任何情况,但也许您可以在您的将父级设置为null(如果更改)的表单:

    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            this.ParentChanged += MyParentChanged;
        }
    
        public void MyParentChanged(Object sender, EventArgs e)
        {
            this.Parent = null;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      相关资源
      最近更新 更多