我有针对.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
仍有同样的问题。
答案 0 :(得分:1)
MessageBox.Show(...)
这不是一个非常有用的片段。它所表明的只是你没有关注最关键的论点。 特别是所以在Office插件中,绝对必须使用,最难正确使用。
这是所有者参数。
非常非常重要。对话框必须让所有者才能正常运行。微软很容易直接指定它。如果您使用的是没有所有者参数的重载,那么它会自行查找所有者。这通常很好。但是你并不总是喜欢它找到的那个,你对UI的控制越少,你开心的可能性就越小。在Office加载项中存在一个明显的问题,它控制着下蹲。
它使用GetActiveWindow()返回的窗口。如果碰巧是由Office程序创建的窗口随后关闭,您将不会感到高兴。这也将关闭消息框。请记住,消息框是模态的,但仅限制用户输入。它不会以任何方式阻止程序关闭窗口。
是的,当你在工作线程上调用它时,你永远不会高兴。 GetActiveWindow()具有线程关联性,活动窗口是每线程属性。将不会有任何其他窗口,因此桌面将成为对话框所有者。没有关闭的风险,但你会有令人讨厌的Z阶问题。任何其他线程拥有的Windows(如Office程序创建的Windows)都不会被禁用。或者换句话说,消息框窗口很容易消失在主窗口后面。用户不能再找到它,他没有提示去寻找它。
您必须指定所有者,不要使用快捷方式。一个明显的选择是Office应用程序的主窗口,就像Excel中的Application.Hwnd属性返回的那样。用于创建IWin32Window实现的示例代码is here。