繁体   English   中英

Form.ShowDialog(IWin32Window) 是否应该与任何 window 句柄一起使用?

[英]Should Form.ShowDialog(IWin32Window) work with any window handle?

使用System.Windows.Forms.ShowDialog(IWin32Window)时,我是否应该能够传入代表任何 window 句柄的IWin32Window并使其相对于 window 是模态的?

作为 Inte.net Explorer 7 扩展的一部分,我试图打开一个关于 Inte.net Explorer 选项卡的 window 模态。 它不是当前选定的选项卡,但我可以获取选项卡的 hwnd 确定。 但是,当我将其传递给 ShowDialog 时,会显示我的表单,但它对任何内容都不是模态的:我仍然可以在 Inte.net Explorer 中执行操作,包括在应该是所有者的选项卡中。 我的表单显示为浮动在 Inte.net Explorer windows 上方,并且它位于顶部,因此它不像是作为普通表单打开的,但它不是正确的模态。

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

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

仅供参考,我正在使用这个包装器 class 从hwnd创建一个IWin32Window (感谢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;
}

更新:使用 Inte.net Explorer 7 & .NET 2.0

更新:更多地使用 Spy++ 及其公开的句柄,我发现如果我使用不同的hwnd ,那么我可以将我的 window 模式设置为选项卡:

我按照IWebBrowser2.HWND 文档的建议使用选项卡的hwnd ,它在 Spy++ 中显示为 class TabWindowClass 它有一个 class Shell DocObject View的孩子,它有一个 Inte.net_Explorer_Server 的孩子。 如果我使用Inte.net Explorer_Serverhwnd ,那么它会正常工作,例如,当我在其他选项卡上单击鼠标时,Inte.net Explorer 会正常反应。 当我在感兴趣的选项卡上单击鼠标时,它会播放 windows d'oh 声音并且不执行任何操作。

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

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

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

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

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

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

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

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

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

I have never tried this from an IE extension, but I have a hunch that IE may not "respect" a Win32-style modal window the same way it does a modal window raised from Javascript using window.open().

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

这是 .NET 中的内置解决方案:

公共 static NativeWindow FromHandle(IntPtr 句柄)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM