常见的模态对话框直到按下alt键才显示

6
我正在构建一个应用程序,它显示一个模态对话框以执行某些操作。该模态对话框使用表单构建,并将主应用程序窗口作为所有者传递给Form.ShowDialog方法。
当单击按钮(FontDialog)时,该模态对话框需要生成常规对话框。常规对话框也显示为模态窗口。
因此,“所有者层次结构”是(A -> B表示A“拥有”B) MainApp -> ModalDialog -> FontDialog
问题是,除非我按下ALT键,否则FontDialog不会以任何方式显示。应用程序的行为几乎符合预期,即当我调用FontDialog.ShowDialog()时,无法将焦点设置到MainApp窗口或ModalDialog,但是FontDialog只是“不可见”,直到我按下ALT键(仅此一个键),然后才会显示出来。
有人知道为什么会发生这种情况吗?我尝试将FormDialog的所有者设置为null(因此使用桌面作为所有者窗口),但它的行为方式相同。
提前致谢。
一些代码
public class SnapshotDialogView : Form
{
        /// bla bla bla


        ///
        /// Button click handler
        private void btnChangeFont_Click(object sender, EventArgs e)
        {
            // this.Owner == MainAppWindow
            DialogResult result = fontDialog.ShowDialog(this);

            if (DialogResult.Cancel == result)
                return;

            Presenter.ChangeLabelsFont(fontDialog.Font);
        }
}

啊,是的,还有一件事。如果在调用FontDialog.ShowDialog()之前隐藏ModalDialogForm(代码中的SnapshotDialogView),那么字体对话框就可以正常显示。

你能发一些你的代码吗?这听起来确实不正常。 - Jon B
代码很正常,但是这里它走了。 - Ricardo Amores
如果在调用fontDialog.ShowDialog(this)之前隐藏ModalForm,则问题可以“解决”,但我不知道是什么原因导致的。 :( - Ricardo Amores
6个回答

5
我曾经使用 MessageBox.Show() 函数时遇到类似的问题。经过一些阅读和测试,我发现这是我重写了一个组件的 onPaint() 函数后的副作用。我猜测当主窗口失去焦点时,由于无法重新绘制,因此任何导致其重新绘制的操作都会使 MessageBox 出现。
我的快速解决方案是,在显示对话框之前将组件的 Visible = false,然后在对话框关闭后将其设置为 true:
    private void btn_Click(object sender, EventArgs e)
    {
        Grid.Visible = false;
        MessageBox.Show("asdf");
        Grid.Visible = true;
    }

我不确定你是否已经找到了其他解决方案,因为这已经过去几个月了。如果你找到了,我很想知道你找到了什么。

编辑:我刚刚读了你的评论,看起来我们找到了类似的解决方案。


实际上,我的所有者表单已经重写了OnPaint方法。 - Ricardo Amores
还有其他解决方案吗?当我引入DataGridView.RowPrePaint事件处理程序时,我开始出现这里描述的行为 - 必须选择ALT键才能显示模态对话框。按照此答案中描述的将Grid.Visible设置为false然后再设置为true的方法可以使模态框显示,但会导致用户体验差。还有其他方法适用于任何人吗?我在Visual Studio C#中。 - Mike Paisner
嘿 @MikePaisner,我已经有一段时间没有使用winforms了,这是一个没有太多活动的旧问题,所以你不太可能在这里找到更多信息。如果其他答案不能解决您的问题,那么提出一个新问题可能会有所帮助。我可以告诉你,我不记得找到过不同的解决方案。我也不认为我的实现中网格可见性的变化对用户有什么影响,但那已经是十年前的事情了,我甚至不记得它是为哪个项目而做的。 - 182764125216
@182764125216 - 昨天在最终找到答案之前发了上面的评论(下面有发布的答案)。非常感谢这个帖子,因为它让我找到了正确的位置。 - Mike Paisner

2
这是一个您所描述的场景的简单示例。
using System;
using System.Drawing;
using System.Windows.Forms;

public class MainAppForm : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainAppForm());
    }
    public MainAppForm()
    {
        Text = "MainAppForm";
        Controls.Add(new Button { Text = "Show ModalDialog", AutoSize = true, Location = new Point(10, 10) });
        Controls[0].Click += (s, e) =>
            {
                using (ModalDialog dlg = new ModalDialog())
                    dlg.ShowDialog(this);
            };
    }
}

public class ModalDialog : Form
{
    public ModalDialog()
    {
        Text = "ModalDialog";
        Controls.Add(new Button { Text = "Show FontDialog", AutoSize = true, Location = new Point(10, 10) });
        Controls[0].Click += (s, e) =>
        {
            using (FontDialog dlg = new FontDialog())
                dlg.ShowDialog(this);
        };
    }
}

它并不表现出你所描述的行为。这意味着你代码中存在错误。

我建议的是,从你的代码中开始移除尽可能多的内容,直到问题消失。这应该可以提示你问题出在哪里。

或者你可以从以上程序开始,然后逐步添加你的代码,直到问题出现。


2
我遇到了与此处描述相同的情况 - 模态对话框未显示,直到选择ALT键。最终,我追踪到问题在DataGridViewCellPaintingEventHandler中。我在单元格绘制事件处理程序中有逻辑来自定义一些单元格的绘制。在某些情况下,我没有设置e.Handled = true。当e.Handled没有被设置为true时,单元格仍然正确绘制,但导致模态对话框框不显示,直到我选择ALT键。在所有情况下正确设置e.Handled=true解决了问题。
此外,以前,我只为需要自定义的单元格定制绘制。现在,我正在绘制和处理所有单元格。对于我不需要自定义的单元格,我执行以下操作:
e.Paint(e.ClipBounds, DataGridViewPaintParts.All);
e.Handled = true;

处理所有单元格的绘制似乎解决了模态对话框未显示,直到按下ALT键的问题。
希望这能帮助某些人,因为它与其他提供的答案有点不同。

1

我不习惯使用.NET编程,但我在我的win32(纯C++)代码中遇到了类似的问题,即MessageBox()函数。 我的错误是没有在WM_PAINT处理程序中的BeginPaint()和EndPaint()函数对中完成绘图。当我添加了这两个函数并在它们之间完成了我的绘图代码后,问题就消失了。虽然我不知道如何在.NET环境中实现这一点:(


0

我在VBNet中遇到了与MessageBox相同的问题。

似乎Windows认为最顶层的窗口不是实际的窗口。在MessageBox.show之前调用BringToFront()可以解决这个问题:

Me.BringToFront()
MessageBox.Show("blablabla", Me.Text, 
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question)

0

尝试使用模态窗体作为您的FontDialog的所有者:

yourFontDialog.ShowDialog(yourModalForm);

抱歉,我可能表达不清楚或者误解了你的意思,但是我所说的ModalDialog是我用Form创建并使用Form.ShowDialog()调用的对话框,我想我们在谈论同一个对话框 :) - Ricardo Amores
@Ricky,是的,我知道了,但是你的FontDialog呢?它是从你的ModalDialog中显示的,对吧?它的所有者是谁? :) - Frédéric Hamidi
主应用程序窗体拥有我的模态窗体,我的模态窗体拥有字体对话框。 - Ricardo Amores
如果在调用fontDialog.ShowDialog(myModalForm)之前隐藏modalForm,则字体对话框会正确显示。但是我使用Visible属性将其隐藏,而不是使用Hide()方法。 - Ricardo Amores

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接