没有用户操作的MessageBox关闭

时间:2015-06-27 13:35:21

标签: c# .net vb.net excel .net-assembly

我有针对.NET 4.0 Client Profile的VB.NET解决方案,其中包括Excel和PowerPoint的加载项。每个都有一个单独的程序集,第三个程序集包含两个共同的代码。因此,通用程序集是其他两个程序集的依赖关系。

有时,但不可预测或不可靠,当 common 程序集中的代码打开MessageBox时,它会在没有用户输入的情况下自动关闭。似乎 调用 程序集(即Excel加载项)从公共程序集中获取了UI的控制权(可能与线程有关?),或者在显示MessageBox时,调用汇编代码继续执行。

我在我的解决方案的各个完全独立的部分中观察到了这种行为,并且无法弄清楚问题是什么。同样,这不会一直发生,我无法可靠地重现这种情况。我在Office 2013的Windows 8.1上测试它。

不幸的是,确实没有任何相关的代码可以发布,除了:

MessageBox.Show(...)

我希望有人可以提供一些有关此处可能发生的事情的见解,并提供修复。

修改

在结合汉斯的建议后,我的代码现在是:

MessageBox.Show(New WindowWrapper(handle), [Message], [Caption], MessageBoxButtons.OK, [Icon])

其中handle [Integer] = Excel.Application.Hwnd和:

Public Class WindowWrapper
  Implements IWin32Window
  Private hwnd As IntPtr

  Public Sub New(handle As IntPtr)
    hwnd = handle
  End Sub
  Public Sub New(handle As Integer)
    hwnd = New IntPtr(handle)
  End Sub

  Public ReadOnly Property Handle As IntPtr Implements IWin32Window.Handle
    Get
      Return hwnd
    End Get
  End Property
End Class

仍有同样的问题。

1 个答案:

答案 0 :(得分:1)

  MessageBox.Show(...)

这不是一个非常有用的片段。它所表明的只是你没有关注最关键的论点。 特别是所以在Office插件中,绝对必须使用,最难正确使用。

这是所有者参数。

非常非常重要。对话框必须让所有者才能正常运行。微软很容易直接指定它。如果您使用的是没有所有者参数的重载,那么它会自行查找所有者。这通常很好。但是你并不总是喜欢它找到的那个,你对UI的控制越少,你开心的可能性就越小。在Office加载项中存在一个明显的问题,它控制着下蹲。

它使用GetActiveWindow()返回的窗口。如果碰巧是由Office程序创建的窗口随后关闭,您将不会感到高兴。这也将关闭消息框。请记住,消息框是模态的,但仅限制用户输入。它不会以任何方式阻止程序关闭窗口。

是的,当你在工作线程上调用它时,你永远不会高兴。 GetActiveWindow()具有线程关联性,活动窗口是每线程属性。将不会有任何其他窗口,因此桌面将成为对话框所有者。没有关闭的风险,但你会有令人讨厌的Z阶问题。任何其他线程拥有的Windows(如Office程序创建的Windows)都不会被禁用。或者换句话说,消息框窗口很容易消失在主窗口后面。用户不能再找到它,他没有提示去寻找它。

必须指定所有者,不要使用快捷方式。一个明显的选择是Office应用程序的主窗口,就像Excel中的Application.Hwnd属性返回的那样。用于创建IWin32Window实现的示例代码is here