WinForms主窗口句柄

15

在我的winforms应用程序中,我试图获取主窗口句柄,以便将其设置为我的wpf模态窗口的父窗口。由于我对winforms不太熟悉,所以经过一番搜索,我找到了两种方法来获取它。

  1. System.Windows.Forms.Application.OpenForms[0].Handle
    
  2. System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
    

(1) 似乎总是返回相同的值,这个值似乎是正确的(至少我的模态窗口的行为符合预期),而 (2) 有时会返回与 (1) 相同的值,但有时会返回完全不同的指针,这个指针似乎无法使用(我的模态窗口出现在每个窗口的顶部,而不仅仅是父窗口)。

有人能解释一下这两种方法之间的区别吗?有时它们返回不同的结果是正常的吗?

编辑:

如果有人还想知道:一旦您获得了句柄,就可以通过创建 WindowInteropHelper 类来使用它:

public static void SetInteropParent(this Window wpfDialogWindow, IntPtr winformsParentHandle)
{
    new WindowInteropHelper(wpdDialogWindow) { Owner = winformsParentHandle }; 
}  

1
@JMK,我需要在我的主窗体上按下一个按钮来显示一个模态窗口,所以我认为可以安全地假设活动窗口始终是相同的。 - Nikita B
1
你不能使用 Form.Handle 吗? - Mo Patel
@MPatel,我手头没有参考资料。而且我也不想注入它。 - Nikita B
1个回答

14

使用 Process.MainWindowHandle 返回错误的句柄并不罕见。Process 类必须猜测哪个窗口是“主要”的窗口,因为本地 winapi 没有指定窗口的机制。所以 Process 猜测第一个窗口是主窗口。这在使用闪屏或登录对话框等应用程序中很容易出错,或者在另一个线程上创建窗口时会出现问题。

Application.OpenForms 没有这个问题,但存在一种失效模式,当窗口被重新创建时,它将无法跟踪窗口。这发生在程序更改仅在创建窗口时才能指定的 Form 的某些属性时。ShowInTaskbar、TransparencyKey 和 Opacity 属性是最常见的问题制造者。

最可靠的方法是覆盖要作为父级的窗体的 OnHandleCreated() 方法。该方法会在 Handle 属性更改时调用。请注意,在您的 WPF 窗口处于活动状态时不要发生这种情况,否则将同时关闭 WPF 窗口。当然很容易观察到 :)

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        SetWpfInteropParentHandle(this.Handle);
    }

SetWpfInteropParentHandle是如何实现的? - dmg
您需要询问楼主,因为他没有发布他的代码。 - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接