【问题标题】:Form.ShowDialog() or Form.ShowDialog(this)?Form.ShowDialog() 还是 Form.ShowDialog(this)?
【发布时间】:2009-05-03 12:03:13
【问题描述】:

我听说如果我在没有指定所有者的情况下调用 form.ShowDialog(),那么可能会出现在屏幕上看不到对话框的情况(它将与其他窗口一起隐藏)。这是真的吗?我使用 ShowDialog() 没有指定所有者数百次,我从来没有遇到过任何问题。

您能否解释一下我在什么情况下会遇到所描述的问题?

更新:

嗯,我做了很多实验,使用 ShowDialog()(没有指定所有者)没有遇到任何真正的意外问题。

所以我认为 ShowDialog() 可能会导致问题只是谣言。 如果您不同意 - 请给我一个导致问题的代码示例。

【问题讨论】:

  • 这似乎不适用于winforms,但为了记录,我来到这里是因为我在WPF中遇到问题。如果我切换到另一个应用程序,当我再次单击父窗体时,子对话框被卡在后面(因为子对话框设置为不在任务栏中显示,这很糟糕)。设置对话框的所有者解决了这个问题。
  • 启动后台工作者并调用 ShowDialog。该窗口不会显示在您的应用程序前面,而是显示在背景上(只是为了惹恼我们的程序员,这种情况偶尔会发生)。
  • Barfieldmv,我尝试按照您的建议进行操作,表单显示在顶部,而不是在背景上。
  • 请给我一个导致问题的代码示例 - 方法错误。契约是MSDN,执行行为是今天的心情。不同版本的 Windows 上的行为可能会有所不同,并且可能会随着 Windows 更新、Windows 功能或其他程序而改变。模态窗口确实有一个所有者,其他所有人都希望您指定正确的所有者。
  • 举个例子:Form1 带有一个可以启动约 1 秒计时器的按钮。计时器的Tick 事件停止计时器,并用ShowDialog 打开Form2。设置Form2.ShowInTaskbar=false,它的行为就像一个弹出窗口。启动程序,单击按钮,然后选择另一个程序在计时器触发之前。单击任务栏图标以再次将您的应用程序置于前台。在我的系统上,我观察到:禁用的 Form1 获得输入焦点(而不是 Form2),并且单击 Form1 不会使 Form2 的标题栏闪烁。

标签: c# .net winforms


【解决方案1】:

我发现 ShowDialog()ShowDialog(this) 的一个烦恼。

运行TestApp,显示newform.ShowDialog(),点击任务栏或快速启动工具栏上的“显示桌面”,点击任务栏上的TestApp。它显示主窗体。您必须使用 Alt-Tab 才能进入您的新表单。

VS

运行TestApp,显示newform.ShowDialog(this),点击任务栏或快速启动工具栏上的“显示桌面”,点击任务栏上的TestApp。它在顶部显示新表单。

【讨论】:

  • 我遇到了您描述的问题。但我已将 ShowDialog() 更改为 ShowDialog(this) 并没有帮助。
【解决方案2】:

只是为了更好地理解所有者拥有的关系:

.NET 允许一个表单“拥有”其他表单。拥有的表格对于 浮动工具箱和命令窗口。拥有表单的一个示例是 Microsoft Word 中的“查找和替换”窗口。当所有者窗口是 最小化时,拥有的表单也会自动最小化。当一个 拥有的表单与其所有者重叠,它始终显示在顶部。

(c) Matthew MacDonald 的“Pro .NET 2.0 Windows 窗体和自定义控件”。


ShowDialog 显示新表单时,隐式关系是 建立 之间的当前活动的形式,称为所有者 形式和新形式,称为拥有形式。这种关系 确保拥有的表单是活动表单并始终显示在 所有者表单的顶部。

这种关系的一个特点是拥有的表单会影响 其所有者表单的行为(使用 ShowDialog 时):

  • 无法最小化、最大化甚至移动所有者表单。
  • 拥有的表单会阻止鼠标和键盘输入到拥有者的表单。
  • 当拥有表单时,所有者表单被最小化。
  • 只能关闭拥有的表单。
  • 如果所有者和自有表单都被最小化并且如果用户按 Alt+Tab 切换到自有表单,则自有表单被激活。

然而,与 ShowDialog 方法不同的是,调用 Show 方法确实可以 不建立隐含的所有者拥有关系。这意味着 任何一种形式都可以是当前活动的形式。

没有隐含的所有者拥有关系,所有者和拥有的形式 alike 可以被最小化、最大化或移动。如果用户关闭任何 主窗体以外的窗体,最近活跃的窗体是 重新激活。

虽然 ShowDialog 建立了隐含的所有者拥有关系, 拥有的表单没有内置方式来回调或查询 打开它的表单。在无模式的情况下,您可以设置新的 窗体的 Owner 属性建立所有者拥有关系。作为一个 快捷方式,您可以将所有者表单作为参数传递给重载 Show 方法,它也接受一个 IWin32Window 参数 (IWin32Window 由 Windows 窗体 UI 对象实现,这些对象公开一个 Win32 HWND 属性通过 IWin32Window.Handle 属性)。

显式模态所有者拥有表单中的表单行为 关系与其隐式模态对应物相同,但 无模式的所有者拥有关系提供了额外的行为 非所有者拥有的无模式案例。一、无模式拥有的形式总是 出现在所有者表单的顶部,即使其中任何一个都可以处于活动状态。 这在您需要保留表单时很有用,例如浮动工具 窗口,在应用程序中的其他表单之上。其次,如果 用户按 Alt+Tab 从所有者切换,拥有的表单如下 套装。为了确保用户知道哪个表单是主表单, 最小化所有者隐藏所有拥有表单的任务栏按钮, 只留下所有者的任务栏按钮可见。

(c) Chris Sells、Michael Weinhardt 撰写的“Windows Forms 2.0 编程”。

【讨论】:

  • 救命稻草,现在我可以做我需要的了
  • 精彩的详细解答!
  • 例如,如果您从单独的线程启动 ShowDialog,则无法知道谁拥有新窗口,因此您可以指定它。
  • 我们能否在控件中获取保存文件对话框(已打开),就像我们使用 Application.OpenForms 获取表单一样?
【解决方案3】:

“当前活动窗口”通常是指前台窗口,但前提是它属于当前线程 - 请参阅 MSDN 中的GetActiveWindow

(实际信息在社区内容中,但评论者是对的,没有“每线程活动窗口”,AFAIK)。

因此,当用户切换到另一个应用程序(或线程)窗口时,您最终会得到一些“默认窗口”。即使 .NET 在这里做了一些魔术,模式也会被破坏:预期的父窗口不会被禁用(例如,您可以切换到主窗口,然后关闭它,或修改某些内容,这通常会由于重入而破坏您的应用程序) .

另外,如果另一个应用程序当前处于活动状态,您的对话框将不会显示在顶部,但会隐藏在某个其他窗口后面。

作为一个小烦恼,初始位置通常不正确或具有误导性。

实际上,这种情况很少发生:如果您打开对话框以响应主窗口上的菜单或按钮单击,则用户实际上永远不会设法切换到另一个窗口。

但是,这在技术上是可行的,如果您打开对话框以响应某些自动化、外部消息等,这很有可能发生。

【讨论】:

  • 作为一般规则,如果可以指定父级,则应指定父级。它从不疼,而且经常有帮助。
  • 我实际上有这个问题 - 我正在从 Outlook 插件运行外部进程 - 它没有显示对话框。任何想法如何显示对话框?它没有任何形式-> 我只想显示一个对话框。如果我之前调用“MessageBox.Show” - 它可以工作 - 否则不会。
  • @bernhardrusch:您是否尝试将 GetDesktopWindow 的 .NET 等效项指定为父级?
【解决方案4】:

无参数 ShowDialog() 仅使用“默认”父级。 对于它的价值,默认父级是“当前活动窗口”是什么。当您关心父母是什么时,您需要明确设置它。

【讨论】:

  • 谢谢,但我知道 ShowDialog() 使用当前活动的窗口,我只是不知道如何出现对话框以用户看不到的方式出现的情况它。
【解决方案5】:

我的问题是从带有ShowDialog() 的表单中调用ShowDialog()。结果是一个隐藏的表单,无法访问它来关闭它。

看完这个话题,我试了ShowDialog(this),效果很好。第二个对话框显示在顶部,居中且功能齐全。当第二个表单设置为Dialogresult.OK 时,它允许访问能够读取其属性然后关闭它的底层对话框。

【讨论】:

    【解决方案6】:

    是的,在某些情况下确实会有所不同。到目前为止,我对无参数方法没有任何问题,我有点惊讶父表单不是默认表单。因此,为避免意外行为,请始终将真正的父窗体传递给 ShowDialog 方法。

    【讨论】:

      【解决方案7】:

      举个例子:

      在您的主窗体中,您有一个启用标签编辑的 ListView。编辑特定标签时,您会启动第二个窗口(在AfterLabelEdit 中使用ShowDialog())。新表单不显示在任务栏中。

      如果您的用户开始编辑标签,然后单击另一个应用程序,则将显示第二个表单,但当返回您的应用程序时,用户只会看到您的主表单,由于显示模式对话框而禁用。然而,通常的闪烁机制(如果单击调用者,将模式对话框变为字体)将不起作用(肯定是因为 AfterEdit 调用尚未返回),并且您的用户将无法到达第二种形式,除非通过循环通过使用 Ctrl+Tab 打开的窗口。

      调用ShowDialog(this) 可以解决这个问题。

      【讨论】:

        【解决方案8】:

        我遇到了这个问题,为了解决它,将 windows 状态属性更改为正常,因为它可能已最小化。

        【讨论】:

        • 我正在使用 Windows 10、1709 和 .NET 4.0 我没有看到您详细说明的这个任务栏场景。也许在您最初发布此内容后已对其进行了修复/调整。
        【解决方案9】:

        我刚刚发现没有使用this 指定所有者导致严重问题的情况。

        启动时,我的应用程序会强制自己进入全屏状态,并确保它始终保持焦点,即使用户尝试 Alt+Tab 退出它,除非您以管理员或开发人员身份登录。

        当我在自定义表单上使用ShowDialog() 时,出于某种原因,对话框出现在我的应用程序后面,并且应用程序本身变得无响应,因为对话框当前处于活动状态。如果我使用ShowDialog(this),那么表单会按预期显示。

        【讨论】:

          猜你喜欢
          • 2019-03-27
          • 2012-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多