2

使用时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 和 .NET 2.0

更新:使用 Spy++ 及其公开的句柄进行更多尝试,我发现如果我使用不同的,hwnd那么我可以使我的窗口模态到选项卡:

我正在使用IWebBrowser2.HWND dochwnd建议的选项卡,它在 Spy++ 中显示为 class 。它有一个 class 的孩子,它有一个 Internet_Explorer_Server 的孩子。如果我使用 的那么它可以正常工作,例如,当我用鼠标单击其他选项卡时,Internet Explorer 会正常反应。当我在感兴趣的选项卡上单击鼠标时,它会播放 windows d'oh 声音并且不执行任何操作。TabWindowClassShell DocObject ViewhwndInternet Explorer_Server

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

此外,就其价值而言,在使用其他窗口句柄时,我通常能够使我的表单成为其他应用程序和对话框的模态。所以我想我的问题的答案是“很多但不是所有的句柄”......可能它取决于应用程序?

更新:另一个旁注:我想让我的表单模式化到选项卡而不是整个窗口的最初原因是,当MessageBox从我的表单打开一个,将表单作为所有者传递时,MessageBox不会总是在我的表单顶部打开. 如果一个新的 Internet Explorer 选项卡刚刚打开但未处于活动状态,则该MessageBox选项卡将被隐藏并且该选项卡将开始闪烁。但是,由于 Internet Explorer 在我的表单打开模式下被禁用,因此无法切换到该选项卡,因此 Internet Explorer 将被冻结。我认为将我的表单模式打开到选项卡可以解决这个问题,但我发现另一个解决方案是避免使用MessageBox:如果我使用第二个表单并且ShowDialog(this)从我的第一个表单开始,那么第二个表单正确打开到前面。所以它似乎Form.ShowDialog()MessageBox.Show()在某些情况下。模态对话框和消息框问题中的更多讨论。

4

4 回答 4

5

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

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

于 2009-02-24T15:43:00.867 回答
2

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

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

于 2009-02-24T14:59:16.617 回答
2

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

internal class WindowWrapper : IWin32Window
{
    public IntPtr Handle { get; private set; }
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}
于 2010-02-26T13:34:18.323 回答
0

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

您是否针对 IE 以外的其他东西测试过这段代码,只是为了确认它在其他应用程序中的工作方式?

于 2009-02-24T14:12:23.127 回答