WinForms主窗口句柄

时间:2013-10-31 09:42:40

标签: c# winforms window-handles

在我的winforms应用程序中,我正在尝试获取主窗口句柄,因此我可以将其设置为我的wpf模式窗口的父级。我对winforms没有太多的经验,所以经过一些谷歌搜索我找到了两种方法来获得它。

  1. System.Windows.Forms.Application.OpenForms[0].Handle
    
  2. System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
    
  3. (1)似乎总是返回看似正确的相同值(至少我的模态窗口按预期行为),而(2)有时返回与(1)相同的值,但有时 - 一个完全不同的指针,似乎不起作用(我的模态窗口出现在每个其他窗口的顶部,而不仅仅是父窗口)。

    有人可以解释这两种方法的区别吗?有时它们会返回不同的结果,这是正常的吗?

    修改

    如果其他人想知道:一旦你掌握了句柄,就可以通过创建WindowInteropHelper类来使用它:

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

1 个答案:

答案 0 :(得分:11)

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