Рукоятка главного окна WinForms

В моем приложении winforms я пытаюсь получить дескриптор главного окна, поэтому я могу установить его как родительский в мое модальное окно wpf. Я не слишком разбираюсь в winforms, поэтому после небольшого поиска в Google я нашел два способа получить его.

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

(1), похоже, всегда возвращает то же значение, которое кажется правильным (по крайней мере мое модальное окно ведет себя как и ожидалось), тогда как (2) иногда возвращает то же значение, что и (1), но иногда - совершенно другой указатель, который, похоже, не работает (мое модальное окно появляется поверх каждого другого окна, а не только родительского окна).

Может кто-нибудь объяснить разницу между этими двумя методами? Нормально ли, что иногда они возвращают разные результаты?

Edit:

В случае, если кто-то еще задается вопросом: как только вы получите дескриптор, вы можете использовать его, создав WindowInteropHelper class:

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

Ответ 1

Для Process.MainWindowHandle, конечно, не редкость возвращать неправильный дескриптор. Класс Process должен угадать, какое окно является "основным". В native winapi нет механизма для обозначения окна как такового. Поэтому Process делает предположение, что первое окно является основным. Это может привести к ошибкам в приложениях, которые используют заставку или диалог входа в систему, и т.д., Или создать окно в другом потоке.

Application.OpenForms не имеет этой проблемы, но имеет режим сбоя, он потеряет отслеживание окна при его воссоздании. Это происходит, когда программа меняет некоторые свойства формы, которые могут быть указаны только при создании окна. Свойства ShowInTaskbar, TransparencyKey и Opacity являются наиболее распространенными нарушителями спокойствия.

Самый надежный способ - переопределить метод OnHandleCreated() формы, в которой вы хотите быть родителем. Которое вызывается всякий раз, когда изменяется свойство Handle. Обратите внимание, что вы хотите убедиться, что этого не происходит, пока окно WPF активно, что также приведет к удалению окна WPF. В противном случае легко заметить, конечно:)

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