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 }; 
}  
4

1 回答 1

14

Process.MainWindowHandle 返回错误句柄当然并不罕见。Process 类必须猜测哪个窗口是“主”窗口。本机 winapi 中没有指定窗口的机制。所以 Process 猜测第一个窗口是主窗口。这在使用闪屏或登录对话框等或在另一个线程上创建窗口的应用程序中出错的诀窍。

Application.OpenForms 没有这个问题,但是有一个失败模式,它会在重新创建一个窗口时失去对它的跟踪。当程序更改只能在创建窗口时指定的窗体的某些属性时,就会发生这种情况。ShowInTaskbar、TransparencyKey 和 Opacity 属性是最常见的麻烦制造者。

最可靠的方法是覆盖您希望成为父窗体的 OnHandleCreated() 方法。每当 Handle 属性更改时都会调用它。请注意,您要确保在 WPF 窗口处于活动状态时不会发生这种情况,这也会杀死 WPF 窗口。否则当然很容易观察:)

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        SetWpfInteropParentHandle(this.Handle);
    }
于 2013-10-31T10:33:48.320 回答