【问题标题】:Windows.Forms.MessageBox in WPF ApplicationWPF 应用程序中的 Windows.Forms.MessageBox
【发布时间】:2014-05-15 21:06:29
【问题描述】:

我正在开发 WPF 应用程序。在它的基于文件的 I/O 函数中,我正在捕获另一个进程使用文件时引发的异常。在这种情况下,应该出现一个带有重试/取消选项的消息框。据我所知,WPF(Windows.MessageBox)中没有这样的消息框,所以我尝试使用 Windows.Forms.Messagebox,但它的行为很奇怪:

当我调用一次时(仅使用 OK-Button-Option 进行测试)...

System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);

...它出现一毫秒,然后消失。

当我调用它两次时...

System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);
System.Windows.Forms.MessageBox.Show("blablabla", "Test", System.Windows.Forms.MessageBoxButtons.OK);

...第二个消息框按预期保持可见,直到您单击“确定”。

我已经尝试使用“null”作为 IWin32Window 的参数,但没有效果。我还尝试将 WPF-Mainwindow 作为参数传递,但(当然)它是错误的类型。

有什么建议吗?

【问题讨论】:

  • WPF 等效于MessageBox。见:stackoverflow.com/questions/3830228/…
  • 使用 WPF 消息框代替 windows 窗体消息窗体。
  • 我知道 System.Windows.Messagebox,但它缺少我打算​​使用的重试/取消按钮。
  • 因为改写消息以适应“是/否”消息框似乎需要“大量”“工作”,您可以尝试设计自己的自定义消息框,您知道自己想要这样做。
  • @MC 不,我不知道 - 这就是为什么我不写只是 some 答案我闭嘴。提出替代方案很好 - 但不能作为答案。如果我问你飞往曼谷的航班多少钱?你不会回答去市中心。只是因为你不知道,对吗?

标签: c# wpf winforms messagebox


【解决方案1】:

您可以使用 Popup 控件创建任何您想要的对话框。

MSDN

An example

More examples

【讨论】:

  • 需要明确的是,这不是模式对话框,对吧?与 MessageBox 相比,这是一个相当重要的区别。
  • 你说得对,它不是 modal。也许这会有所帮助:bradleach.wordpress.com/2009/02/25/control-level-modal-dialog。在 cmets 中,他们描述了使用(透明)矩形来“禁用”与“模态对话框”下方的元素的交互。这有点工作,但据我所知,这是获得自定义模式对话框的唯一方法
【解决方案2】:

WinForms 消息框功能不能在 WPF 应用程序中工作没有多大意义。毕竟,这两个 API 都调用了原生的 Win32 MessageBox 函数。

该问题可能与 System.Windows.Forms.MessageBox 实现中的代码有关,该代码尝试禁用所有窗口以准备显示模式对话框。这可能无法与某些 WPF 管道正确交互,从而产生一些奇怪的行为。当然是推测;我不是 WPF 方面的专家。

然而,我确实仔细阅读了参考源中的 System.Windows.MessageBox 实现,并且不禁注意到它省略了 WinForms 实现用于禁用其他窗口的代码。它只是直接调用 Win32 MessageBox 函数,在这两种情况下我都会这样做。我确信 WinForms 团队的决定有充分的理由,我只是不知道它是什么。

那该怎么办?像其他人一样,我的第一个倾向是告诉您使用专门设计用于 WPF 应用程序的 MessageBox 函数。但就像你说的,它不支持重试或取消按钮。没有充分的理由不这样做,WPF 团队似乎没有公开访问此功能。也许微软的 UI 人员正试图阻止使用重试和取消按钮?无论如何,你可以通过 P/Invoking Win32 MessageBox 函数得到你想要的:

    private const int MB_RETRYCANCEL   = 0x00000005L;

    private const int IDCANCEL         = 2;
    private const int IDRETRY          = 4;

    private const int MB_DEFBUTTON1  = 0x00000000;
    private const int MB_DEFBUTTON2  = 0x00000100;

    private const int MB_ICONERROR       = 0x00000010;
    private const int MB_ICONWARNING     = 0x00000030; 
    private const int MB_ICONINFORMATION = 0x00000040;

    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern int MessageBox(HandleRef hWnd,
                                        string text,
                                        string caption,
                                        int type);

直接自己调用:

switch (MessageBox(new HandleRef(null, owner),  // your owner window
                   "My Message Text",           // your message
                   "Message",                   // the dialog box title/caption
                   MB_RETRYCANCEL | MB_ICONERROR | MB_DEFBUTTON1))
{
    case IDRETRY:
    {
        // ...
    }
    case IDCANCEL:
    {
        // ...
    }
    default:
    {
        throw new NotSupportedException("MessageBox is displayed only with Retry and Cancel buttons; any other response is not supported and should be impossible.");
    }
}

result 将是 IDRETRYIDCANCEL。你可以指定任何你想要的图标,或者省略它以没有图标。而MB_DEFBUTTON1 指定重试按钮是默认的。使用MB_DEFBUTTON2 将取消按钮设为默认按钮。

但实际上,您应该使用 TaskDialog,而不是 MessageBox。我认为 WPF 会有一个包装器,但网络搜索表明它没有。 Windows API Code Pack 确实,不管是否过时。

【讨论】:

  • 感谢您提供有关 Windows.MessageBox 和 Windows.Forms.Messagebox 背后的答案和信息。也适用于“解决方法”。我认为,我将采用“阻力最低的方式”并使用 Windows.MessageBox 并改写文本,以便给定的 MessageBoxButtons-options 有意义。
  • @tafk 呃,我不知道。从用户体验的角度来看,“你想重试吗?是/否”远没有明确标记为“重试/取消”的按钮那么清晰。研究一再表明,用户不会阅读消息文本,他们只需单击一个按钮即可尽快关闭消息框。在按钮上有正确的标题会让一切变得不同。这就是为什么替换 MessageBox 的新 API TaskDialog 允许您完全指定 自定义 按钮标题。
【解决方案3】:

尝试 System.Windows.MessageBox 而不是 System.Windows.Forms.MessageBoxSystem.Windows.MessageBox 是 WPF 版本。

它是 PresentationFramework.dll 文件的一部分。

来源:MSDN

【讨论】:

  • 我知道 System.Windows.Messagebox,但它缺少我打算​​使用的重试/取消按钮。
  • 你不能改写你的消息,以便可用的 MessageBoxButton 选项就足够了吗?
  • 是的,当然。而不是说“文件被另一个进程阻止[重试] [取消]”我可以说“文件被另一个进程阻止。重试访问?[是] [否]”或类似的话,我可能会这样做如果没有其他解决方案。我只是想知道为什么 Windows.Forms.Messagebox 不能按预期工作。 (我猜我还可以搜索带有重试/取消选项的自定义 Windows.Messagebox)。
【解决方案4】:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多