Form.ShowDialog(IWin32Window)应该可以使用任何窗口句柄吗?

时间:2009-02-24 14:03:55

标签: c# .net winforms modal-dialog bho

使用System.Windows.Forms.ShowDialog(IWin32Window)时,我是否应该传入代表任何窗口句柄的IWin32Window,并将其设置为该窗口的模态?

作为Internet Explorer 7扩展的一部分,我正在尝试打开与Internet Explorer选项卡相关的窗口模式。它不是当前选中的选项卡,但我可以获得选项卡的hwnd。但是,当我将它传递给ShowDialog时,我的表单会显示出来,但它不是关于任何形式的模态:我仍然可以在Internet Explorer中执行操作,包括在应该是所有者的选项卡中。我的表单显示在Internet Explorer窗口上方,它保持在顶部,因此它不像它只是作为普通表单打开,但它不是正确的模态。

使用Spy++,我可以找到我的表单,并且正确设置了所有者句柄。

这是否意味着出了问题,或者我做错了什么?如何正确地模态我的表单?

仅供参考,我正在使用此包装类从IWin32Window创建hwnd(感谢Ryan!):

/// <summary>
/// Wrapper class so that we can return an IWin32Window given a hwnd
/// </summary>
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
    public WindowWrapper(IntPtr handle)
    {
        _hwnd = handle;
    }

    public IntPtr Handle
    {
        get { return _hwnd; }
    }

    private IntPtr _hwnd;
}

更新:使用Internet Explorer 7&amp; .NET 2.0

更新:使用Spy ++及其公开的句柄来玩更多内容,我发现如果我使用不同的hwnd,那么我可以将窗口模态设置为选项卡:

我正在使用IWebBrowser2.HWND doc建议的标签hwnd,它在Spy ++中显示为类TabWindowClass。它有一个类Shell DocObject View的子级,其子级为Internet_Explorer_Server。如果我使用hwnd的{​​{1}},那么它可以正常工作,例如,当我在其他选项卡上单击鼠标时,Internet Explorer会正常响应。当我在感兴趣的标签上点击鼠标时,它会播放windows d'oh声音并且什么都不做。

我还不知道如何以编程方式获取Internet_Explorer_Server Internet Explorer_Server,但它应该是可能的。

另外,对于它的价值,在玩其他窗口句柄时,我通常能够将其表单模式转换为其他应用程序和对话框。所以我想我的问题的答案是'很多但不是所有句柄'......可能取决于应用程序?

更新:另一个注意事项:我想将表单模式设置为选项卡而不是整个窗口的原因是,当从表单中打开hwnd时,将表单作为所有者传递,{ {1}}并不总是在我的表单上打开。如果刚刚打开了一个新的Internet Explorer选项卡但未激活,则MessageBox将被隐藏,该选项卡将开始闪烁。但是,由于Internet Explorer已禁用我的表单打开模式,因此无法切换到该选项卡,因此Internet Explorer将被冻结。我认为打开我的表单模式到选项卡可以解决这个问题,但我发现另一个解决方案是避免使用MessageBox:如果我使用第二个表单并从我的第一个表单中使用MessageBox那么第二个表单形式正确地打开到前面。因此,MessageBox似乎在某些情况下比ShowDialog(this)效果更好。 Problems with modal dialogs and messageboxes

中的更多讨论

4 个答案:

答案 0 :(得分:5)

ShowDialog()做了两件重要的事情。它开始抽取一个消息循环,因此它以模态方式对调用代码起作用。并且它通过EnableWindow(false)API调用禁用应用程序中的任何其他窗口。后者是你的情况没有发生的事情。考虑到需要禁用的窗口不是WF窗口,这并不奇怪。

您可能需要自己调用EnableWindow()。确保在对话框关闭之前重新启用它,否则Windows将寻找另一个应用程序的窗口来关注。

答案 1 :(得分:2)

您的代码是正确的。您可能遇到的问题是IE有一个与其选项卡相关的线程模型。我不知道确切的细节,但简短的版本是每个选项卡可以并且可能在与其他选项卡不同的线程上运行。

对话框的模态特定于运行对话框的线程。其他线程上的UI不受另一个线程上的模型对话框的影响。由于这个原因,您完全有可能访问在不同线程上运行的选项卡。

答案 2 :(得分:2)

这是Ryan / Rory的WindowWrapper代码的更简洁版本:

internal class WindowWrapper : IWin32Window
{
    public IntPtr Handle { get; private set; }
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}

答案 3 :(得分:0)

我从来没有尝试过IE扩展程序,但我预感到IE可能不会“尊重”Win32风格的模态窗口,就像它使用window.open().从Javascript引发的模式窗口一样

您是否针对IE之外的其他内容测试了此代码,只是为了确认它的工作方式与其他应用程序一样?